鱼C论坛

 找回密码
 立即注册
查看: 3897|回复: 1

[汇编作业] 汇编语言_课程设计1

[复制链接]
发表于 2021-2-11 23:03:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

下面这个代码我敲了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:[di],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:[di]         ;年份转入数据段
           mov ds:[si],ax
           mov ax,es:[di+1]
           mov ds:[si+1],ax
           mov ax,es:[di+2]
           mov ds:[si+2],ax
           mov ax,es:[di+3]
           mov ds:[si+3],ax
         
           mov ax,0                  ;向字符串填入0结尾
           mov ds:[si+4],ax
           
           mov si,0                   ;输出年份
       pop dx
       mov dl,12
       mov cl,2
       call show_str
           push dx
           
           mov ax,es:[di+84]           ;总收入转化成acsell码转入数据段
       mov dx,es:[di+86]
       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:[di+168]           ;总雇员转化成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:[di+84]           ;计算人均收入的总收入
       mov dx,es:[di+86]
           mov cx,es:[bp+168]
           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:[si],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:[si]
           jcxz ok      
           mov es:[di],cl
           mov es:[di+1],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
        
还是发不了图,积分不够,不过我运行过了,是对的哦!
累了,累了,大家加油,好好学习,如果可以的话,帮我刷刷回帖,多顶顶,爱你们哦!

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
weiter + 5 + 5 加油呀,新年快乐!

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-3-3 15:45:28 | 显示全部楼层
收藏了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-23 08:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表