鱼C论坛

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

[汇编作业] 课程设计1

[复制链接]
发表于 2018-12-11 16:13:49 | 显示全部楼层 |阅读模式

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

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

x
注解已加上,如有看的迷糊的地方我只能说抱歉了,我也就能这么注释了,因为我自己也是边调试边修改的,这是我第一个写到200行多一点的汇编程序如有不对的地方请多多指教
终于完事了,课程设计1按照作业的方式实现了输出,在这里要特别感谢@人造人 感谢他对我程序中出现的问题进行细心的指导,和对我备注方面的指教谢谢啊
  1. assume cs:code, ds:data;, ds:table, ss:stack

  2. data segment
  3.         db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985','1986','1987','1988','1989','1990','1991','1992','1993','1994','1995'
  4.         dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
  5.         dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
  6.         dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
  7.         dw 11542,14430,15257,17800
  8. data ends   

  9. stack segment
  10.                 db 512 dup (0)
  11. stack ends

  12. code segment

  13. divdw:
  14.                 push ax
  15.                 mov ax, dx
  16.                 mov dx, 0
  17.                 div cx
  18.                
  19.                 mov bx, ax
  20.                 pop ax
  21.                 div cx
  22.                  
  23.                 mov cx, dx
  24.                 mov dx, bx
  25.                
  26.                 ret
  27. average_str:                        ;该段输出人均收入,收入/雇员=人均
  28.                 push ax
  29.                 push bp
  30.                 push dx
  31.                 push es
  32.                 push cx
  33.                 push di
  34. average_one:
  35.                 push cx            
  36.                 mov bx, 0
  37.                 mov ax, word ptr ds:[si + 84]  ;因有被除数大于65536所以调用两个寄存器ax储存低位
  38.                 add si, 2
  39.                 mov dx, word ptr ds:[si + 84]  ;被除数高位传给dx寄存器
  40.                 add si, 2
  41.                 div word ptr ds:[di + 168]      ;int(16位位移/(H * 65536 + L))
  42.                 add di, 2                                                ;
  43.                 push di                                                        ;因为下面的程序还需要使用di所以暂时把di中的数据放入栈中当此段程序结束开始下一个循环前在用pop调出付给di
  44.                 mov di, 0                       ;因为已经把di中的数据放入栈中所以现在可以初始化di中的数据为零让下面的程序可以使用di寄存器
  45. average_two:                            ;下面的程序就跟employee_str中的程序相似,上面的数据相当于em中的mov ax, word ptr ds:[si]
  46.                 mov cx, 10
  47.                 mov dx, 0
  48.                 div cx
  49.                 add dx, '0'
  50.                 push dx
  51.                 inc bx
  52.                 mov cx, ax
  53.                 jcxz average_three
  54.                 jmp short average_two
  55. average_three:
  56.                 mov cx, bx
  57. average_four:
  58.                 pop ax
  59.                 mov ah, 2
  60.                 mov byte ptr es:[bp + di], al
  61.                 mov byte ptr es:[bp + di + 1], ah
  62.                 add di, 2
  63.                 loop average_four
  64.                 pop di                              ;恢复di中的数据,已备循环使用div word ptr ds:[di + 168]
  65.                 pop cx
  66.                 add bp, 160
  67.                 loop average_one
  68.                
  69.                 pop di
  70.                 pop cx
  71.                 pop es
  72.                 pop dx
  73.                 pop bp
  74.                 pop ax
  75.                 ret
  76. employee_str:                   ;因为该段跟下面的运行方式差不多再次就不做标注了该段是输出雇员的数据
  77.                 push ax
  78.                 push bp
  79.                 push dx
  80.                 push es
  81.                 push cx
  82.                 push di
  83. employee_one:
  84.                 push cx
  85.                 mov bx, 0
  86.                 mov ax, word ptr ds:[si]
  87.                 add si, 2
  88. employee_two:
  89.                 mov cx, 10
  90.                 mov dx, 0
  91.                 div cx
  92.                 add dx, '0'
  93.                 push dx
  94.                 inc bx
  95.                 mov cx, ax
  96.                 jcxz employee_three
  97.                 jmp short employee_two
  98. employee_three:
  99.                 mov cx, bx
  100. employee_four:
  101.                 pop ax
  102.                 mov ah, 2
  103.                 mov byte ptr es:[bp + di], al
  104.                 mov byte ptr es:[bp + di + 1], ah
  105.                 add di, 2
  106.                 loop employee_four
  107.                 pop cx
  108.                 mov di, 0
  109.                 add bp, 160
  110.                 loop employee_one
  111.                
  112.                 pop di
  113.                 pop cx
  114.                 pop es
  115.                 pop dx
  116.                 pop bp
  117.                 pop ax
  118.                 ret
  119. income_str:
  120.                 push ax
  121.                 push bp
  122.                 push dx
  123.                 push es
  124.                 push cx
  125.                 push di
  126. income_one:
  127.                 push cx         ;把cx压入栈中,因为cx还需要被调用,压入栈中后就可以暂时保存起来后期再调用
  128.                 mov bx, 0                ;进行第二次循环的时候bx中带有数值,所以这里要进行归零设置
  129.                 mov ax, word ptr ds:[si]
  130.                 add si, 2
  131.                 mov dx, word ptr ds:[si]
  132.                 add si, 2
  133. income_two:
  134.                 push bx               ;下面的计算中我们需要用到bx寄存器所以先把bx中的数据压入栈中暂存
  135.                 mov cx, 10       ;除数
  136.                 call divdw                 ;无溢出除法运算
  137.                 pop bx           ;bx调出里面的数据是inc bx自加后的数
  138.                 add cx, '0'
  139.                 push cx          ;把无溢出除法运算中得到的余数推入栈中
  140.                 inc bx           ;因为下面我们还需要从栈中取出上面计算的余数这个是用来计数的记录我们一共向栈中压入了多少余数
  141.                 mov cx, ax       ;divdw中的商传给cx已被jcxz income_three验证使用
  142.                 jcxz income_three ;如验证cx中的数值为0就跳转到income_two标识处向下执行
  143.                 jmp short income_two ;无条件跳转到标识处起到循环的作用
  144. income_three:
  145.                 mov cx, bx                        ;把上面计数的bx中的数值传给cx供loop income_four使用
  146. income_four:
  147.                 pop ax               ;取出栈中的余数
  148.                 mov ah, 2            ;显示属性
  149.                 mov byte ptr es:[bp + di], al
  150.                 mov byte ptr es:[bp + di + 1], ah
  151.                 add di, 2
  152.                 loop income_four     ;此处为内循环,输出每一行相应的数字
  153.                 pop cx               
  154.                 mov di, 0
  155.                 add bp, 160
  156.                 loop income_one      ;行数循环,控制参数在上面pop cx这个
  157.                
  158.                 pop di                                 ;从栈中取回寄存器中的初始化数据
  159.                 pop cx
  160.                 pop es
  161.                 pop dx
  162.                 pop bp
  163.                 pop ax
  164.                 ret
  165.                
  166. year_str:
  167.                 push ax
  168.                 push bp
  169.                 push dx
  170.                 push es
  171.                 push cx
  172.                 push di          ;因为下一个call还需要使用以上寄存器所以先把这些寄存器的初始值保存到栈中,在该段程序执行完毕后再取出再对应的寄存器中
  173. year_one:
  174.                 push cx     ;在year_str这段程序又再次使用了push cx因为loop year_one循环
  175.                 mov cx, 4        ;该cx给year_two使用
  176. year_two:
  177.                 mov al, byte ptr ds:[si]      ;内存地址储存的数据需要一个通用寄存器才能储存在其他的内存地址中所以这里面借用了一个al寄存器
  178.                 mov byte ptr es:[bp + di], al ;
  179.                 mov byte ptr es:[bp + di + 1], ah
  180.                 inc si                                                   ;因为需要循环拾取数据所以si自加
  181.                 add di, 2         
  182.                 loop year_two                  ;此处为内循环,一共申诉出21行4列的字符这个循环控制每行中的列数
  183.                 pop cx                                                   ;取出给loop year_one使用
  184.                 mov di, 0                      ;bp加了160他就可以去下一行输出,所以di从零开始
  185.                 add bp, 160                                           ;bp加160
  186.                 loop year_one                                   ;行循环
  187.                
  188.                 pop di                         ;取回,本次结束
  189.                 pop cx
  190.                 pop es
  191.                 pop dx
  192.                 pop bp
  193.                 pop ax
  194.                 ret
  195. start:       
  196.                 mov ax, data
  197.                 mov ds, ax
  198.                 mov ax, 0b800h
  199.                 mov es, ax
  200.                 mov ax, stack
  201.                 mov ss, ax
  202.                 mov sp, 512
  203.                 mov bp, 480         ;从什么地方开始
  204.                 mov cx, 21          ;输出多少行
  205.                 mov ah, 2           ;输出属性
  206.                 mov di, 0
  207.                 mov si, 0
  208.                 call year_str       ;年月输出
  209.                
  210.                 mov bp, 500                   ;从新定义bp的数值已被es:使用
  211.                 call income_str    ;从从该处开始输出收入
  212.                
  213.                 mov bp, 520        ;从新定义bp的数值已被es:使用
  214.                 call employee_str
  215.                
  216.                 mov bp, 540
  217.                 mov si, 0
  218.                 call average_str
  219.                
  220.                 mov ax, 4c00h
  221.                 int 21h
  222.        
  223.                
  224. code ends
  225. end start
复制代码

下面为运行的结果
4.gif

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
人造人 + 5 + 5 + 3 鱼C有你更精彩^_^

查看全部评分

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

使用道具 举报

发表于 2019-1-25 14:22:22 | 显示全部楼层
楼主牛批 加油
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-26 04:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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