奥普瓯江 发表于 2018-12-11 16:13:49

课程设计1

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

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

stack segment
                db 512 dup (0)
stack ends

code segment

divdw:
                push ax
                mov ax, dx
                mov dx, 0
                div cx
               
                mov bx, ax
                pop ax
                div cx
               
                mov cx, dx
                mov dx, bx
               
                ret
average_str:                      ;该段输出人均收入,收入/雇员=人均
                push ax
                push bp
                push dx
                push es
                push cx
                push di
average_one:
                push cx            
                mov bx, 0
                mov ax, word ptr ds:;因有被除数大于65536所以调用两个寄存器ax储存低位
                add si, 2
                mov dx, word ptr ds:;被除数高位传给dx寄存器
                add si, 2
                div word ptr ds:      ;int(16位位移/(H * 65536 + L))
                add di, 2                                                ;
                push di                                                        ;因为下面的程序还需要使用di所以暂时把di中的数据放入栈中当此段程序结束开始下一个循环前在用pop调出付给di
                mov di, 0                     ;因为已经把di中的数据放入栈中所以现在可以初始化di中的数据为零让下面的程序可以使用di寄存器
average_two:                            ;下面的程序就跟employee_str中的程序相似,上面的数据相当于em中的mov ax, word ptr ds:
                mov cx, 10
                mov dx, 0
                div cx
                add dx, '0'
                push dx
                inc bx
                mov cx, ax
                jcxz average_three
                jmp short average_two
average_three:
                mov cx, bx
average_four:
                pop ax
                mov ah, 2
                mov byte ptr es:, al
                mov byte ptr es:, ah
                add di, 2
                loop average_four
                pop di                              ;恢复di中的数据,已备循环使用div word ptr ds:
                pop cx
                add bp, 160
                loop average_one
               
                pop di
                pop cx
                pop es
                pop dx
                pop bp
                pop ax
                ret
employee_str:                   ;因为该段跟下面的运行方式差不多再次就不做标注了该段是输出雇员的数据
                push ax
                push bp
                push dx
                push es
                push cx
                push di
employee_one:
                push cx
                mov bx, 0
                mov ax, word ptr ds:
                add si, 2
employee_two:
                mov cx, 10
                mov dx, 0
                div cx
                add dx, '0'
                push dx
                inc bx
                mov cx, ax
                jcxz employee_three
                jmp short employee_two
employee_three:
                mov cx, bx
employee_four:
                pop ax
                mov ah, 2
                mov byte ptr es:, al
                mov byte ptr es:, ah
                add di, 2
                loop employee_four
                pop cx
                mov di, 0
                add bp, 160
                loop employee_one
               
                pop di
                pop cx
                pop es
                pop dx
                pop bp
                pop ax
                ret
income_str:
                push ax
                push bp
                push dx
                push es
                push cx
                push di
income_one:
                push cx         ;把cx压入栈中,因为cx还需要被调用,压入栈中后就可以暂时保存起来后期再调用
                mov bx, 0                ;进行第二次循环的时候bx中带有数值,所以这里要进行归零设置
                mov ax, word ptr ds:
                add si, 2
                mov dx, word ptr ds:
                add si, 2
income_two:
                push bx             ;下面的计算中我们需要用到bx寄存器所以先把bx中的数据压入栈中暂存
                mov cx, 10       ;除数
                call divdw               ;无溢出除法运算
                pop bx         ;bx调出里面的数据是inc bx自加后的数
                add cx, '0'
                push cx          ;把无溢出除法运算中得到的余数推入栈中
                inc bx         ;因为下面我们还需要从栈中取出上面计算的余数这个是用来计数的记录我们一共向栈中压入了多少余数
                mov cx, ax       ;divdw中的商传给cx已被jcxz income_three验证使用
                jcxz income_three ;如验证cx中的数值为0就跳转到income_two标识处向下执行
                jmp short income_two ;无条件跳转到标识处起到循环的作用
income_three:
                mov cx, bx                        ;把上面计数的bx中的数值传给cx供loop income_four使用
income_four:
                pop ax               ;取出栈中的余数
                mov ah, 2            ;显示属性
                mov byte ptr es:, al
                mov byte ptr es:, ah
                add di, 2
                loop income_four   ;此处为内循环,输出每一行相应的数字
                pop cx               
                mov di, 0
                add bp, 160
                loop income_one      ;行数循环,控制参数在上面pop cx这个
               
                pop di                               ;从栈中取回寄存器中的初始化数据
                pop cx
                pop es
                pop dx
                pop bp
                pop ax
                ret
               
year_str:
                push ax
                push bp
                push dx
                push es
                push cx
                push di        ;因为下一个call还需要使用以上寄存器所以先把这些寄存器的初始值保存到栈中,在该段程序执行完毕后再取出再对应的寄存器中
year_one:
                push cx   ;在year_str这段程序又再次使用了push cx因为loop year_one循环
                mov cx, 4        ;该cx给year_two使用
year_two:
                mov al, byte ptr ds:      ;内存地址储存的数据需要一个通用寄存器才能储存在其他的内存地址中所以这里面借用了一个al寄存器
                mov byte ptr es:, al ;
                mov byte ptr es:, ah
                inc si                                                   ;因为需要循环拾取数据所以si自加
                add di, 2         
                loop year_two                  ;此处为内循环,一共申诉出21行4列的字符这个循环控制每行中的列数
                pop cx                                                   ;取出给loop year_one使用
                mov di, 0                      ;bp加了160他就可以去下一行输出,所以di从零开始
                add bp, 160                                           ;bp加160
                loop year_one                                   ;行循环
               
                pop di                         ;取回,本次结束
                pop cx
                pop es
                pop dx
                pop bp
                pop ax
                ret
start:       
                mov ax, data
                mov ds, ax
                mov ax, 0b800h
                mov es, ax
                mov ax, stack
                mov ss, ax
                mov sp, 512
                mov bp, 480         ;从什么地方开始
                mov cx, 21          ;输出多少行
                mov ah, 2         ;输出属性
                mov di, 0
                mov si, 0
                call year_str       ;年月输出
               
                mov bp, 500                   ;从新定义bp的数值已被es:使用
                call income_str    ;从从该处开始输出收入
               
                mov bp, 520      ;从新定义bp的数值已被es:使用
                call employee_str
               
                mov bp, 540
                mov si, 0
                call average_str
               
                mov ax, 4c00h
                int 21h
       
               
code ends
end start
下面为运行的结果

swjqwe 发表于 2019-1-25 14:22:22

楼主牛批 加油
页: [1]
查看完整版本: 课程设计1