王爽汇编里的课程设计为何我写的程序显示的是乱码?

xuanfeng157 2007-01-01 12:59:15
以下程序是王爽汇编里的课程设计我写了n多遍,改了好几天了,就是总达不到想要的结果,请问各位高手哪个地址错了?

程序任务:
将以下数据显示在屏幕上
年份 年总收入 员工人数 人均收入
1975 16 3 ?
1976 22 7 ?
1977 382 9 ?
1978 1356 13 ?
1979 2390 28 ?
1980 8000 38 ?
1981 16000 130 ?
1982 24486 220 ?
1983 50065 476 ?
1984 97479 778 ?
1985 140417 1001 ?
1986 197514 1442 ?
1987 345980 2258 ?
1988 590827 2793 ?
1989 803530 4037 ?
1990 1183000 5635 ?
1991 1843000 8226 ?
1992 2759000 11542 ?
1993 3753000 14430 ?
1994 4649000 15257 ?
1995 5937000 17800 ?


程序:
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',0
;以上是表示21年的21个字符串
dd 16,22,382,1356,2390,8000,16000,24486
dd 50065,97479,140417,197514,345980,590827,803530,1183000
dd 1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收的21个dword型数据
dw 3,7,9,13,28,38,130,220
dw 476,778,1001,1442,2258,2793,4037,5635
dw 8226,11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
tempdata segment
db 8 dup(0)
tempdata ends
code segment
start:mov ax,data
mov ds,ax ;将数据段data段地址送入ds
mov ax,0b800h
mov es,ax ;将显存基地址送入es
sub cx,cx ;将cx清0
mov bx,0 ;把数据段data偏移地址指向data:0
mov di,0 ;把显存偏移地址指向b800:0
mov si,0 ;雇员地址偏移量
throwout:mov cl,ds:[bx]
jcxz finished ;检测数据是否显示完毕,若是转到finished
mov dl,02h
mov al,ds:[bx]
mov es:[di],al
mov es:[di+1],dl ;将年份字段第一个字符送入显存es:[di]
mov al,ds:[bx+1]
mov es:[di+2],al
mov es:[di+3],dl;将年份字段第二个字符送入显存es:[di+2]
mov al,ds:[bx+2]
mov es:[di+4],al
mov es:[di+5],dl;将年份字段第三个字符送入显存es:[di+4]
mov al,ds:[bx+3]
mov es:[di+6],al
mov es:[di+7],dl;将年份字段第四个字符送入显存es:[di+6]
mov ax,ds:[bx+55h]
mov dx,ds:[bx+57h];将收入总数字段dd送入寄存器dx(高16位)、ax(低16位)
mov bp,32 ;将偏移地址指向收入总数字段的第一个单元地址
call dtoc ;调用子程序dtoc,将收入总数字段送入显存es:[sp+di]
mov ax,ds:[si+0a9h]
mov dx,0 ;将雇员字段dw送入寄存器ax
call getbp ;调用子程序getbp,计算每条记录雇员字段在显存中的起始地址
call dtoc ;调用子程序dtoc,将雇员字段送入显存es:[sp+di]
mov ax,ds:[bx+55h]
mov dx,ds:[bx+57h]
mov cx,bx
mov bx,ds:[si+0a9h];将收入总数字段dd送入寄存器dx(高16位)、ax(低16位),将雇员字段dw送入寄存器bx
call divdw ;调用子程序divdw,计算人均收入的值
mov bx,cx
mov cx,0
call getbp ;调用子程序getbp,计算每条记录人均收入字段在显存中的起始地址
call dtoc ;调用子程序dtoc,将人均收入字段送入显存es:[sp+di]
add bx,4
add si,2
add di,160 ;以上3句是为下一次循环时存放数据做准备
jmp throwout ;若数据未显示完毕,跳转至throwout进入下次循环
finished:mov ax,4c00h ;数据显示完毕,返回dos
int 21h
;以下是子程序dtoc,功能:将数字型数据转换成字符,并将其送入显存;参数:dd数据(用ax,dx传送),每条记录在显存中的偏移量bp,di;返回:每条记录在显存中的偏移量bp,为下一字段做准备
dtoc:push si
push ds
push bx
push cx
mov si,0
mov bx,tempdata
mov ds,bx
s:mov cx,ax
jcxz ok
mov bx,0ah
call divdw
add cl,30h
mov ds:[si],cl
inc si
jmp s
ok:mov bh,02h
mov cx,si
a:mov bl,ds:[si]
mov es:[bp+di],bl
mov es:[bp+di+1],bh
sub si,1
add bp,2
loop a
pop cx
pop bx
pop ds
pop si
ret
;以下是子程序divdw,计算两数值的商及余数
divdw:push si ;ax,dx,bx ax,dx,cx
push ax
mov ax,dx
mov dx,0
div bx
mov si,ax
pop ax
div bx
mov cx,dx
mov dx,si
pop si
ret
;以下是子程序getbp,偏移量bp的值
getbp:push ax ;bp bp
push bx
mov ax,bp
mov bx,0
mov bl,32
div bl
sub bl,ah
add bp,bx
pop bx
pop ax
ret
code ends
end start
...全文
272 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuanfeng157 2007-01-03
  • 打赏
  • 举报
回复
感谢zara(Kyrie eleison)指点
zara 2007-01-01
  • 打赏
  • 举报
回复
大致有两个问题吧. 第一是在 throwout: 循环中, 在计算平均值时, 将 bx 通过 cx 来进行保存, 但 divdw 子程却是使用了 cx 的, 所以 cx 的值发生改变了. 这个保存失效. 可以通过堆栈来进行 "保存-恢复":
...
mov dx,ds:[bx+57h]
push bx ;* mov cx,bx 这里压栈保存 bx
mov bx,ds:[si+0a9h] ;将收入总数字段 ....
call divdw ;调用子程序divdw,计算人均收入的值
pop bx ;* mov bx,cx 这里出栈恢复 bx
mov cx,0
...

第二个问题就是在 dtoc 子程中, 最后现实结果钱, si 指向的是有效字符串的后面. 比如第一个值 16, 转换后的字符串为 "61", si 指向的不是 '1' 而是 '1' 的后面一个字节. 所以 si 应该先减去 1:
...
ok:mov bh,02h
mov cx,si
dec si ;*+ 这里!
a:mov bl,ds:[si]
...

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧