王爽汇编学习课程设计1,写完后体会不少。写代码时间不长,调试用了6小时左右。让我明白,想写出好的接口还真不容易。
assume cs:codesg
; 除了年份每个用12个字符存储,最后一个是0
datasetsg 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个年号
dd 16, 22, 382, 1356, 2390, 8000, 1600, 24486, 50056, 97479, 140417, 197514
dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4648000, 5937000
; 21年收入
dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
; 21年 员工人数
datasetsg ends
; 由于程序调用比较多,栈要申请空间多一些
stacksg segment
dw 128 dup(0)
stacksg ends
; 最后放置数据的table
table segment
db 21 dup('year s n ? ',0)
; 5 13 6 7
table ends
; dtocsg 用于中间存储使用
dtocsg segment
db 10 dup(0)
dtocsg ends
; table 段地址: 14a1
codesg segment
start:
mov ax, stacksg
mov ss, ax
mov sp, 128
mov ax, datasetsg
mov es, ax
mov ax, table
mov ds, ax
; cx -- 21 年的数据
mov cx, 21
mov bx, 0
mov bp, 0
mov si, 0
; bp 目的数据
s:
mov di, 0
mov ax, es:[si]
mov dx, es:[si + 2]
mov ds:[bp + di], ax
mov ds:[bp + di + 2], dx
add di, 5
; 以上移动年份
mov ax, es:[84 + si]
mov dx, es:[84 + si + 2]
push si
mov si, bp
add si, di
call dwtoc
pop si
add di, 13
; 以上移动总收入
push dx
push ax
mov ax, es:[168 + bx]
mov dx, 0
push si
mov si, bp
add si, di
call dwtoc
pop si
add di, 6
; 以上移入公司员工人数
; 以下计算平均收入
pop ax
pop dx
push cx
mov cx, es:[168 + bx]
call divdw
pop cx ; 丢弃余数
push si
mov si, bp
add si, di
call dwtoc
pop si
; 这里碰到问题,原因为div指令执行结果是商存放在低位,而余数存放在高位
; 以上移动总人数及平均收入
add di, 7
mov byte ptr ds:[bp + di], 0
inc di
push dx
push cx
push si
mov si, bp
mov dh, cl ;打印行号,刚开始dh一直设为0,结果是看不到数据。不过cl是从21开始减为0.所以列表是倒置的。反正是打印成功,就不修改这个问题了。
; 编程中有一个体会,有的参数传给子函数后是需要子函数修改的,此时就不用push到栈中,直接拿来用。
mov dl,0
mov cl,3
call far ptr show_str
pop si
pop cx
pop dx
add si, 4
add bx, 2
add bp, di
loop s
mov ax, 4c00h
int 21h
; ax=word型数据,若显示dword,则高位位于dx,低位位于ax,显示均用10进制,可自定义(这个也简单)
; ds:si 指向字符串首地址
dwtoc:
push dx
push cx
push bx
push ax
push si
push di
push ds
push es
mov bx, ax
mov ax, ds
mov es, ax
mov ax, dtocsg
mov ds, ax
mov ax, bx
mov di, 0
loop_dtoc:
mov cx, 10
call divdw
; (divdw) ; ax=低16位 ; dx=高16位 ; cx=除数 ; (output) ; dx=商的高16位, ax=商的低16位 ; cx=余数
mov bx, cx
add bl, 30h
mov [di], bl
mov cx, dx
jcxz jdx0
jmp short jmp_jdx0
jdx0:
mov cx, ax
jcxz backdwtoc
jmp_jdx0:
inc di
jmp short loop_dtoc
backdwtoc:
mov cx, di
inc cx ; di由0开始,所以cx要加1
loop_backdwtoc:
mov bl, ds:[di]
mov es:[si], bl
inc si
sub di, 1
loop loop_backdwtoc
pop es
pop ds
pop di
pop si
pop ax
pop bx
pop cx
pop dx
ret
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
; (input)
; ax=低16位
; dx=高16位
; cx=除数
; (output)
; dx=商的高16位, ax=商的低16位
; cx=余数
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
divdw:
push bx
push si
; 先计算高位dx的商与余数
; 备份ax-->bx中
mov bx, ax
mov ax, dx
mov dx, 0
div cx
; 备份第一次除法商在si
mov si, ax
;进行第二步除法
mov ax, bx
div cx
mov cx, dx
mov dx, si
back_divdw:
pop si
pop bx
ret
;dh 行号,dl 列号 cl 颜色 ,遇到0返回 ds:[si]首地址
show_str:
push ax
push bx
push es
push di
push si
push cx
;push dx
; 计算偏移量
mov al, 160
mul dh
mov bx, ax
mov al, 2
;mov dl, 2
mul dl
add bx, ax
; 偏移量存储在bx中
mov ax, 0b800h
mov es, ax
mov di, 0
mov ah, cl
mov ch, 0
print:
mov cl, ds:[si]
jcxz backshow_str
mov al, cl
mov es:[bx + di], ax
;mov es:[bx + di +1], al
add di, 2
inc si
jmp short print
backshow_str:
;pop dx
pop cx
pop si
pop di
pop es
pop bx
pop ax
retf
codesg ends
end start