一个程序的bug弄了一天,苦思无果,希望坛友旁观者清
这个题目的要求是将图片1的数据打印到显存中如图片2,可是我debug到子程序show_4str中的代码- mov es:[di],ax-时,t后发现他的数据并没有改成正确的数值31(字符1)左思右想这句代码应该没有问题,我的显存地址B800:00A2也没有计算错误,不太明白,请各位坛友指教,现在将debug图附上。
希望有坛友赐教
[img=http://my.csdn.net/my/album/show/124849][/img]
assume cs:code
data 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'
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
db 168 dup(0)
data ends
stack segment
db 32 dup(0)
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,32
mov ax,0B800h
mov es,ax
mov di,0
mov si,0
;=========年份写入显存段========
mov dh,1
mov dl,1
mov cx,21
s1:
push cx
mov bp,4
mov cl,2
call show_4str
inc dh
pop cx
loop s1
;========收入写入显存段=========
mov cx,21
mov di,84
s2:mov ax,ds:[di]
add di,2
mov dx,ds:[di]
add di,2
mov si,294;ds:[si]指向字符串的首地址
call dtoc
push cx
mov dh,1
mov dl,16
mov cl,2
call show_str
pop cx
loop s2
;========雇员写入显存段=========
mov cx,21
mov di,168
s3:mov ax,ds:[di]
add di,2
mov dx,0
mov si,294
call dtoc
push cx
mov dh,1
mov dl,32
mov cl,2
call show_str
pop cx
loop s3
;=======人均收入写入显存段=======
mov cx,21
mov di,84
s4:mov ax,ds:[di]
add di,2
mov dx,ds:[di]
mov bp,168
div word ptr ds:[bp];其实这里更好的思路就是用除法程序divdw,因为人均收入也可能占用4个字节,但是我假设它只占用2个字节,事实上,只要这个课程设计能够做好,这个就没多大事情了
add bp,2
mov dx,0
mov si,294;ds:[si]指向字符串的首地址
call dtoc
mov dh,1
mov dl,48
push cx
mov cl,2
call show_str
pop cx
loop s4
mov ax,4c00h
int 21h
;======4个字符写入显存的特殊子程序show_4str======
;参数:ds:si指向字符串的首地址,dh=行号(范围0-24),dl=列号(范围0-79)
;cl=颜色,bp=字符串长度
show_4str:
push ax
push di
push si
push bp
push cx
mov al,160
mul dh
mov di,ax
mov al,2
mul dl
add di,ax;di显存偏移地址,es显存段基址
mov bl,cl;bl暂存颜色值
mov cx,bp
a:mov al,ds:[si]
inc si
mov ah,bl
mov es:[di],ax ;es:[di]显存段
add di,2;除参数和cs:ip外,其他寄存器参数都要入栈,不知道这种想法是否正确?
loop a
pop cx
pop bp
pop si
pop di
pop ax
ret
;======数值显示dtoc=======
;参数:ax=低16位dx=高16位
;ds:si指向字符串的首地址
;返回:无
dtoc:
push si
push di
push cx
mov di,0
b:mov cx,10
call divdw
push cx
add di,1;si记录入栈次数
mov cx,ax
jcxz ok1
jmp short b
ok1:
mov cx,dx
jcxz ok2;dx和ax的值都为0,表示除完,除法过程结束
jmp short b
ok2:mov cx,si
c1:pop ax
add al,30h;al从数值变为字符
mov ds:[si],al
inc si
;mov ax,2
;mov ds:[si],al;给字符添加属性颜色绿色
;inc si;感觉这几行不需要额,不过还是写出来了
loop c1
mov byte ptr ds:[si],0
pop cx
pop di
pop si
ret
;=========显示字符串show_str=========
;参数:(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79)
;(cl)=颜色,ds:si指向字符串的首地址
;返回:无
;应用举例:在屏幕的8行3列,用绿色显示data段中的字符串
show_str:
push bp
push bx
push ax
push di
push si
mov al,dh
mov bl,160
mul bl
mov di,ax
mov al,dl
mov bl,2
mul bl;偏移地址=dh*160+dl*2
add di,ax;di存显存缓冲区的偏移地址,es存段基址
mov bl,cl ;bl暂存cl的颜色值,好像只有bx可用了,要不cl的值就要入栈了
d:
mov al,ds:[si]
mov ah,bl
mov es:[di],ax
mov cl,ds:[si]
mov ch,0
add si,2
add di,2
jcxz e
jmp short d
e:
pop si
pop di
pop ax
pop bx
pop bp
ret
;======除法程序divdw======
;参数:(ax)=dword型数据的低16位 (dx)=dword型数据的高16位
;(cx)=除数
;返回:(dx)=结果的高16位 (ax)=结果的低16位
;(cx)=余数
divdw:
push si
push di
mov di,ax
mov ax,dx;先求int(H/N)
mov dx,0
div cx
mov si,ax;si存着高16位的值
mov ax,di;再求[rem(H/N)*65536+L]/N,此时ax存着高16位,dx存着低16位
div cx ;ax存着低16位 dx余数
mov cx,dx
mov dx,si
pop di
pop si
ret
code ends
end start