635924705 发表于 2021-2-11 23:03:23

汇编语言_课程设计1

【交流学习,共同进步】
【大家新年快乐啊!!!恭喜发财,红包拿来!!!!】

下面这个代码我敲了4个小时,头都大了,终于搞定了,不过还是存在很多可以优化的地方,有想法的小伙伴可以试试把我的代码优化一下哦!
还是那句话,我暂时没看小甲鱼老师的答案讲解。因为,只有不看答案,我的结题思路才会是全部原创的,哈哈哈哈。这样做出来的代码,才有更大的交流学习的价值。
assume cs:code, ss:stack

datasg segment
      db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
      db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
      db '1993','1994','1995'
      ;以上是表示21年的21个字符串,一共84个字节
      
      dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
      dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
      ;以上是表示21年公司总收入的21个dword型的数据,一共84个字节
      
      dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
      dw 11542,14430,15257,17800
      ;以上是表示21年公司雇员人数的21个word型的数据,一共42个字节
datasg ends

data segment                ;数据段默认用0结尾
    dw 24 dup(0)
data ends

stack segment               ;我用了较多的栈空间,怕溢出,自己定义了一个栈
    dw 32 dup(0)   
stack ends

code segment
start: mov ax,stack         ;初始化栈段
       mov ss,ax
           mov sp,32

           mov ax,data            ;初始化数据段
       mov ds,ax
          
           mov ax,datasg          ;初始化待转化的数据段
           mov es,ax
          
       mov si,0               ;si记录数据段记录的位置,永远指向结尾的0
           mov di,0               ;di记录待转化数据段的当前转化位置,低指向下一个待转化的地址,0是年份的开始,84是是总收入的起始,168是雇员人数的起始
          
           mov dh,2                ;提前定dh行数
          
          
      
            
           push es                ;置零原先显存上第一页的数据,每一页显存4000个字节,从d8000h开始
           mov ax,0b800h
           mov es,ax
           mov ax,0
       mov cx,2000
clear_gpu:
       mov es:,ax
           add di,2;
           loop clear_gpu
           pop es
           mov di,0

           mov cx,21
dfg:   
       push cx
       push dx
       mov si,0          
           mov ax,es:         ;年份转入数据段
           mov ds:,ax
           mov ax,es:
           mov ds:,ax
           mov ax,es:
           mov ds:,ax
           mov ax,es:
           mov ds:,ax
       
           mov ax,0                  ;向字符串填入0结尾
           mov ds:,ax
          
           mov si,0                   ;输出年份
       pop dx
       mov dl,12
       mov cl,2
       call show_str
           push dx
          
           mov ax,es:         ;总收入转化成acsell码转入数据段
       mov dx,es:
       mov si,12                  ;si指向总收入开始的地址,使其为12   
           call dtoc_plus             ;将ax和dx中的doubleword数据,变成字符串,记录在当前ds:【si】的位置,记录完成后si指向字符串末尾的0

       mov si,12                   ;输出公司总收入
           pop dx
       mov dl,24
       mov cl,2
       call show_str       
       push dx          
          
       mov si,24                   ;si指向总雇员开始的地址,使其为24
          
           push di                            ;di入栈保存,cx入栈保存
           push cx
          
       mov ax,di                           ;使di=二分之一的di
           mov cx,2
           mov dx,0       
           div word ptr cx
           mov di,ax
           mov bp,ax                     ;额外用bp存放二分之一的di
          
           mov ax,es:         ;总雇员转化成acsell码转入数据段
       mov dx,0          
           call dtoc_plus             ;将ax和dx中的doubleword数据,变成字符串,记录在当前ds:【si】的位置,记录完成后si指向字符串末尾的0
                     
       pop cx                     ;还原cx与di
           pop di
          
       mov si,24                  ;输出雇员人数
           pop dx
       mov dl,36
       mov cl,2
       call show_str
           push dx
          
           mov ax,es:         ;计算人均收入的总收入
       mov dx,es:
           mov cx,es:
           div word ptr cx
           mov dx,0
          
           mov si,36                  ;si指向人均收入开始的地址,使其为12   
           call dtoc_plus             ;将ax和dx中的doubleword数据,变成字符串,记录在当前ds:【si】的位置,记录完成后si指向字符串末尾的0
          
           mov si,36                   ;输出人均收入
           pop dx
       mov dl,48
       mov cl,2
       call show_str
                     
          
           add di,4
           add dh,1
           pop cx
           dec cx
           jcxz yui
           jmp dfg
          
yui:mov ax,4c00h
       int 21h
;将ax和dx中的doubleword数据用字符串的acsll码,记录在当前ds:【si】的位置,用0做结束,结束时si指向0所在位置
dtoc_plus:
    push dx            ;保留原函数的值
        push cx
        push ax
        push bx

   
        mov bx,0         ;先入栈一个0作为字符串的结尾
        push bx
       
in_stack:             ;处理dword数据的acsll值,并存入栈中
        mov cx,10
    call divdw         ;dx被除数高16位,ax被除数低16位,cx除数,商的高16位在dx,低16位在ax,余数给cx
       
        add cx,30h         ;acsll码值入栈
        push cx
                        
        mov cx,dx          ;双重检查,只有当ax和dx都是0才会通过
        inc cx
        loop in_stack
        mov cx,ax
        inc cx
        loop in_stack
       
out_stack:       
    pop ax             ;栈里面是按word型存储的,但是,因为存进去的数不可能超过8位,所以只有low位有值,取al即可
    mov ds:,al
        inc si
    mov cx,ax
        inc cx
    loop out_stack       
    dec si             ;si回去一位,指向0
       

        pop bx
    pop ax
        pop cx
        pop dx
    ret
       
;dx被除数高16位,ax被除数低16位,cx除数,结果的高16位给dx,低16位给ax,余数给cx          
divdw:
push bx         ;保存可能变动的值

push ax
mov ax, dx ;高16位
mov dx, 0 ; (新组合的32位的被除数)=0000 000fh
div cx   ;此时(dx)=余数 和 低16位 组合成一个新的32位的被除数
mov bx, ax ;结果的高16位
pop ax   ;低16位
div cx
mov cx, dx ;余数
mov dx, bx ;结果的高16位

pop bx
ret       
;将dh看作行号(0-24),dl看作列号(0-79),cl看作颜色,
;ds:si指向字符串首地址,0为结束的字符串,放入显存指定位置,结束时si指向0所在位置
show_str:
       push ax               ;因为不知道主函数是否用了ax,先进栈保存,后续会使用ax寄存器
           push di               ;因为不知道主函数是否用了di,先进栈保存,后续会使用di寄存器
           push es               ;因为不知道主函数是否用了es,先进栈保存,后续会使用es寄存器
           push cx               ;后面会对cx改动
           push dx
                     
       mov ax,0b800h         ;显存起始地址给es,用di记录位置
       mov es,ax
                    
           mov di,0
          
           mov al,160            ;每行160个字节,每个字符2个字节,计算字节位置后,给di寄存器
           mul dh
           mov dh,0
           add ax,dx
           add ax,dx
           mov di,ax
          
           mov al,cl                ;写入字符串
           mov ch,0
read_in:
       mov cl,ds:
           jcxz ok      
           mov es:,cl
           mov es:,al
           add di,2
           inc si
           jmp short read_in       
                     
ok:   pop dx
       pop cx   
       pop es
           pop di
           pop ax
       ret           
code ends
end start
       
还是发不了图,积分不够,不过我运行过了,是对的哦!
累了,累了,大家加油,好好学习,如果可以的话,帮我刷刷回帖,多顶顶,爱你们哦!{:10_264:}

10449123 发表于 2021-3-3 15:45:28

收藏了{:5_106:}
页: [1]
查看完整版本: 汇编语言_课程设计1