首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

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

2012-03-09 
王爽汇编里的课程设计为何我写的程序显示的是乱码?以下程序是王爽汇编里的课程设计我写了n多遍,改了好几天

王爽汇编里的课程设计为何我写的程序显示的是乱码?
以下程序是王爽汇编里的课程设计我写了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


[解决办法]
大致有两个问题吧. 第一是在 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]
...

热点排行