作为一个其中考试性质的课程设计,的确有一定难度,缩了前面学习到的各个存储器的使用,栈的使用,函数设计以及调用技巧,转移函数使用(在这个课题设计中犯了两次jmp和jczx+loop使用的错误,印象深刻),经过今天6个小时的努力,终于顺利实现。这里实现dtoc功能的时候没有按上一个测试那样使用0结尾,为的是方便整行输出数据,这里不影响整体实现。不多说,上代码,上的图有一张是之前错误显示的,是因为对jmp和loop的使用错误而致。
assume cs:code
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982'
db '1983','1984','1985','1986','1987','1988','1989','1990'
db '1991','1992','1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486
dd 50065,97479,140417,197514,345980,590827,803530,1183000
dd 1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,223
dw 476,778,1001,1442,2258,2793,4037,5635
dw 8226,11542,14430,15257,17800
data ends
table segment
db 21 dup (31 dup (' '),0) ;32个字符
table ends
code segment
start:
;先把数据以字符形式输出到table里
mov ax,table
mov ds,ax
mov si,0
mov ax,data
mov es,ax
mov bx,0
mov cx,21
mov di,0
;输出目标地点的行列数据
mov dl,0;列
mov dh,3;行
s:
push cx;保存cx
push si;保存输出数据源的起始位置
push dx;保存输出目标地点的行列数据
mov ax,word ptr es:[bx]
mov ds:[si],ax;输出年份前两位
mov ax,word ptr es:[bx+2]
add si,2
mov ds:[si],ax;输出年份后两位
mov dx,es:[bx+86];被除数高位
add si,4
mov ax,es:[bx+84];被除数低位
add si,2
push ax
push dx
;输出为字符串
call dtoc
mov cx,es:[bx+di+168];被除数
add si,8
;输出为字符串
mov ax,cx
mov dx,0
call dtoc
pop dx
pop ax
;计算除法结果到ax,dx
call divdw
add si,8
call dtoc
;把table该行数据都全部输出到界面
pop dx
inc dh
mov cl,00100100B
pop si
call show_str
add si,32
add bx,4
sub di,2
pop cx
loop s
mov ax,4c00H
int 21H
dtoc: ;功能:将dword型数据转变为表示十进制数的字符串,字符串以0为结尾符
; 注:为实现整行输出,单个词不以0结尾。
;参数:(ax)=word型数据 低16位
; (dx)=word型数据 高16位
; ds:si指向字符串首地址 (‘0’:30H,‘9’:39H)
push bx
push cx
push si
push di
mov di,0;用来记录输出字符长度
dtoc_k:
mov cx,ax
jcxz dtoc_r
mov cx,10
call divdw
mov bx,30H
add bx,cx
push bx;字符入栈,解决字符输出顺序问题
inc di
jmp dtoc_k;修正使用loop dtoc_k的错误,这里应该是动态循环
dtoc_r:
;字符出栈
mov cx,di
jcxz dtoc_end
dtoc_p:
pop bx;从高到低出栈
mov ds:[si],bl;注意只输出一个字符
inc si
loop dtoc_p
dtoc_end:
pop di
pop si
pop cx
pop bx
ret
divdw: ;功能:进行不会产生溢出的除法运算,被除数为dword型
; 除数为word型,结果为dword型
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位,(cx)=余数
push bx
;push dx不应该把dx进栈,这是要输入和输出的数据
push di
push si
;先算00ax/cx商si余数di,再算00dx/cx商bx余数为dx,然后算dxdi/cx余数dx
mov bx,dx
mov dx,0
div cx
mov di,dx;余数最大为cx-1
mov si,ax;商最大为 0000 FFFF
mov ax,bx
mov dx,0
div cx ; bx00/cx
mov bx,ax;商最大为 0000 FFFF
;余数dx最大为 cx-1
mov ax,di
div cx ; dxdi/cx
add si,ax;商最大为 0000 FFFF, si不可能溢出
mov cx,dx
mov dx,bx
mov ax,si
pop si
pop di
;pop dx
pop bx
ret
show_str: ;功能: 在指定的位置,用指定的颜色,
; 显示一个用0结束的字符串
;参数: (dh)=行号(0~24),(dl)=列号(0~79),
; (cl)=颜色,ds:si字符串首地址
;返回:无
push ax
push bx
push cx
push dx
push es
push si
;确定输出第一个偏移位置bx
mov ax,0B800H
mov es,ax
mov al,dh
mov ah,160
mul ah
mov dh,0
add ax,dx
add ax,dx
mov bx,ax
mov ah,cl ;颜色保存在高位
mov ch,0
show_str_s:
mov cl,ds:[si]
jcxz show_str_ok
mov al,cl
mov es:[bx],ax
add bx,2
inc si
jmp short show_str_s
show_str_ok:
pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start