泡泡吧 发表于 2017-1-10 04:29:50

程序设计一,字符写入问题,求大神告知下

问题: 程序设计一,为何在指定长度写入的数据还会导致文字错乱? 代码如下:
assume cs:codesg ,ss:data,ds:table

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 11452,14430,15257,17800
   ;数组格式存放
data ends

table segment
db 42 dup (0)
table ends


codesg segment       
start:        mov bx,0
                mov di,0
                mov dx,0
                mov cx,15h
                mov ax,table
                mov ds,ax
                mov ax,data
                mov ss,ax
s:                mov si,0
                mov ax,word ptr ss:               
                mov word ptr ds:,ax
               
                mov ax,word ptr ss:.2
                mov word ptr ds:.2,ax ;年份装入ds:si中
                add si,6
               
                push dx
                mov ax, word ptr ss:.54h
                push ax
                mov ax, word ptr ss:.56h
                push ax
                mov ax,0ah
                push ax
                call dtoc ;收入转入ds:si
                add si,6
               
                mov ax,word ptr ss:.0a8h
                push ax
                mov ax,0
                push ax
                mov ax, 0ah
                push ax
                call dtoc ;人员转入ds:si中
                add si,6
               
               
                push cx
                mov ax, word ptr ss:.54h
                push ax
                mov ax, word ptr ss: .56h
                push ax
                mov ax,word ptr ss:.0a8h
                push ax
                call divdw;平均收入转入ds:si中
                pop cx
                push ax
                push dx
                mov ax,0ah
                push ax
                call dtoc
                add si,6
               
               
                mov si,0
                mov ax,24h
                push ax
                call dtoc1 ;将ds:si中的字符串0转为空格
               
                pop dx
                mov ax,ds
                push ax
                mov ax,02
                push ax
                push dx
                mov ax,0
                push ax
                call show1; 将数值显示在屏幕上               
               
               
                inc dx
                add di,2
                add bx,4
               
                loop s
               
                       
                mov ax,4c00h
                int 21h       
               

;功能名: dtoc1
;说明: 将指定长度ds:si中的字符串0转为空格
;参数: ax=长度,ds:si指向字符串首地址
;结果: (ds:si)指向字符串的首地址,字符串以0结尾               
;源码始
dtoc1:        mov bp,sp
                push cx
                mov cx,
e:                push cx
                mov cl,ds:
                jcxz b
c:                inc si
                pop cx
                loop e
                mov al,0
                mov ds:,al
                pop cx
                ret 2
               
b:                mov al,20h
                mov ds:,al
                jmp short c
;源码终
;功能名: dtoc
;说明: 将word型数据转变为表示十进制数的字串符,字符串以0结尾,最大转换15byte字符
;参数: ax=dword型数据低16位
;参数: dx=dword型数据高16位
;参数: bx=word型数据,如果除数为0表示求(dx)(ax)/0ah十进制数的字串符,非0表示进行divdw转变为十进制数的字串符
;结果: (ds:si)指向字符串的首地址
;源码始
dtoc:        push dx
                push di
                push cx               
                mov bp,sp
                mov di,0
                mov ax, ;(ax)
                mov dx, ;(dx)
dtocs:        mov cx, ;型数据,如果除数为0表示求(dx)(ax)/0ah十进制数的字串符,非0表示进行divdw转变为十进制数的字串符
                jcxz dtocz
                push ax   ;非0表示进行divdw转变为十进制数的字串符
                push dx
                push cx
dtocc:        call divdw
                jmp short dtoce
dtocz:        push ax
                push dx
                mov cx,0ah
                push cx
                jmp short dtocc
dtoce:        add cl,30h
                mov ch,0               
                push cx
                inc di
                mov cx,dx
                jcxz dtocr;如果 余数为0
dtocr:        mov cx,ax
                jcxz dout
                jmp short dtocs ;如果商不为零继续除
               
dout:         mov cx,di
dtoct:        pop ax
                mov byte ptr ds:,al ;写入中
                inc si
                loop dtoct
                pop cx       
                pop di
                pop dx
                ret 6
;源码终
;功能名: divdw
;说明: 进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
;参数: push ax=dword型数据低16位
;参数: push dx=dword型数据高16位
;返回: dx=结果的高16位,ax=结果的低16位 cx=余数
;源码始
divdw:
                push si
                mov bp,sp
                mov ax, ;高16位数据
                mov dx,0
                mov cx,
                div cx      
                mov si,ax
                mov ax,
                div cx       
                mov cx,dx
                mov dx,si
                pop si
               
                ret        6                       
;源码终

;功能名: show1
;说明: 向屏幕显示文本,以零结尾文本
;参数: push ax 文本,以零结尾
;参数: push ax 文本颜色,
;参数: push ax 行,从零开始 范围(0-24)
;参数: push ax 列,从零开始 范围(0-80),偶数递增
;结果: 向指定行显示指定文本
;源码始:
show1:push di
                push bx
                push cx
                push si
                push dx
                mov bp,sp
                mov ax,
                mov ds,ax
                mov ax,0b800h;屏幕显示地址
      mov es,ax
                mov ax, ;行
               
                add ax,4
      mov bx,160   ;第一行4*160
                mul bx
      mov bx,ax       
      mov si,
                mov di,0
show_s1:mov cl,ds:   ;ds:指向文本byte单元               
                mov ch,0
      jcxz show_s0;如果=0直接返回
                mov ch,      ;颜色
      mov es:,cx ;显示
      add si,2
                inc di
       
               
      loop show_s1
show_s0:pop dx
                pop si
                pop cx
                pop bx
                pop di
                ret 8
;源码终



codesg ends
endstart

泡泡吧 发表于 2017-1-10 05:46:21

自己解决了,终于知道问题出现在哪里了.dtoc 中

;功能名: dtoc
;说明: 将word型数据转变为表示十进制数的字串符,字符串以0结尾,最大转换15byte字符
;参数: ax=dword型数据低16位
;参数: dx=dword型数据高16位
;参数: bx=word型数据,如果除数为0表示求(dx)(ax)/0ah十进制数的字串符,非0表示进行divdw转变为十进制数的字串符
;结果: (ds:si)指向字符串的首地址
;源码始
dtoc:      push dx
                push di
                push cx               
                mov bp,sp
                mov di,0
                mov ax, ;(ax)
                mov dx, ;(dx)
dtocs:      mov cx, ;型数据,如果除数为0表示求(dx)(ax)/0ah十进制数的字串符,非0表示进行divdw转变为十进制数的字串符
                jcxz dtocz
                push ax   ;非0表示进行divdw转变为十进制数的字串符
                push dx
                push cx
dtocc:      call divdw
                jmp short dtoce
dtocz:      push ax
                push dx
                mov cx,0ah
                push cx   ;这里进行push 导致 mov cx,,错位了.用另外一个寄存器保存下被除数就好了.
                jmp short dtocc
dtoce:      add cl,30h
                mov ch,0               
                push cx
                inc di
                mov cx,dx
                jcxz dtocr;如果 余数为0
dtocr:      mov cx,ax
                jcxz dout
                jmp short dtocs ;如果商不为零继续除
               
dout:         mov cx,di
dtoct:      pop ax
                mov byte ptr ds:,al ;写入中
                inc si
                loop dtoct
                pop cx      
                pop di
                pop dx
                ret 6
;源码终

{:10_257:}{:10_257:}

泡泡吧 发表于 2017-1-10 07:05:45

泡泡吧 发表于 2017-1-10 05:46
自己解决了,终于知道问题出现在哪里了.dtoc 中

;功能名: dtoc


精简后代码如下:
assume cs:codesg ,ss:data,ds:table

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 11452,14430,15257,17800
   ;年人总数数组
data ends

table segment
db 42 dup (0)
table ends


codesg segment       
start:        mov bx,0
                mov di,0
                mov dx,0
                mov cx,15h
                mov ax,table
                mov ds,ax
                mov ax,data
                mov ss,ax
s:                mov si,0
                mov ax,word ptr ss:               
                mov word ptr ds:,ax
               
                mov ax,word ptr ss:.2
                mov word ptr ds:.2,ax ;年份装入ds:si中
                add si,6
               
                push dx ;入栈显示行
                mov ax, word ptr ss:.54h
                push ax
                mov ax, word ptr ss:.56h
                push ax
                call dtoc ;收入转入ds:si
                add si,8
               
                mov ax,word ptr ss:.0a8h
                push ax
                mov ax,0
                push ax
                call dtoc ;人员转入ds:si中
                add si,4
               
               
                push cx ;入栈cx,保存循环次数
                mov ax, word ptr ss:.54h
                push ax
                mov ax, word ptr ss: .56h
                push ax
                mov cx,word ptr ss:.0a8h
                call divdw;平均收入转入ds:si中
                pop cx   ;出栈cx,取出循环次数
                push ax
                push dx
                call dtoc
                               
                mov si,0
                mov ax,24h
                push ax
                call dtoc1 ;将ds:si中的字符串0转为空格
               
                pop dx
                mov ax,02 ;颜色
                push ax   ;颜色
                push dx   ;行
                mov ax,0
                push ax
                call show1; 将数值显示在屏幕上               
               
               
                inc dx
                add di,2
                add bx,4
               
                loop s
               
                       
                mov ax,4c00h
                int 21h       
               

;功能名: dtoc1
;说明: 将指定长度ds:si中的字符串0转为空格
;参数: ax=长度,ds:si指向字符串首地址
;结果: (ds:si)指向字符串的首地址,字符串以0结尾               
;源码始
dtoc1:        mov bp,sp
                push cx
                mov cx, ;将长度赋值给cx
e:                push cx;保存长度
                mov cl,ds:;获取ds:si字符
                jcxz b   ;是否为零,如果为零调到b,进行转为空格
c:                inc si   ;不为零,ds:si 指向下一个字符
                pop cx   ;取出cx,
                loop e
                mov al,0
                mov ds:,al;字符串以0结尾
                pop cx
                ret 2               
b:                mov al,20h
                mov ds:,al
                jmp short c
;源码终
;功能名: dtoc
;说明: 将word型数据转变为表示十进制数的字串符,字符串以0结尾,最大转换15byte字符
;参数: ax=dword型数据低16位
;参数: dx=dword型数据高16位
;结果: (ds:si)指向字符串的首地址
;源码始
dtoc:        push dx
                push di
                push cx
                mov bp,sp
                mov di,0
                mov ax, ;(ax)
                mov dx, ;(dx)
dtocz:        push ax
                push dx
                mov cx,0ah
                call divdw;进行除法               
                add cl,30h;余数转为字符串
                mov ch,0        ;高位=0       
                push cx   ;入栈字符串
                inc di      ;记录字符个数
                mov cx,dx   
                jcxz dtocr;如果 余数为0
dtocr:        mov cx,ax   ;如果商为零,跳到dtoct ,跳出循环,
                jcxz dout
                mov cx,bx; 将被除数赋值给cx
                jmp short dtocz ;如果商不为零继续除               
dout:         mov cx,di
dtoct:        pop ax
                mov byte ptr ds:,al ;写入中
                inc si
                loop dtoct
                pop cx       
                pop di
                pop dx
                ret 4
;源码终
;功能名: divdw
;说明: 进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
;参数: push ax=dword型数据低16位
;参数: push dx=dword型数据高16位
;参数: cx=word型数据被除数
;返回: dx=结果的高16位,ax=结果的低16位 cx=余数
;源码始
divdw:
                push si
                mov bp,sp
                mov ax, ;高16位数据
                mov dx,0
                div cx      
                mov si,ax;保存高位商
                mov ax, ;低16位数据
                div cx       
                mov cx,dx
                mov dx,si;赋值给dx,高位商
                pop si
                ret        4                       
;源码终

;功能名: show1
;说明: 向屏幕显示文本,以零结尾文本
;参数: push ax 文本,以零结尾
;参数: push ax 文本颜色,
;参数: push ax 行,从零开始 范围(0-24)
;参数: push ax 列,从零开始 范围(0-80),偶数递增
;结果: 向指定行显示指定文本
;源码始:
show1:push di
                push bx
                push cx
                push si
                push dx
                mov bp,sp
                mov ax,0b800h;屏幕显示地址
      mov es,ax
                mov ax, ;行               
                add ax,4
      mov bx,160   ;第一行4*160
                mul bx
      mov bx,ax       
      mov si, ;列
                mov di,0
show_s1:mov cl,ds:   ;ds:指向文本byte单元               
                mov ch,0
      jcxz show_s0;如果=0直接返回
                mov ch,      ;颜色
      mov es:,cx ;显示
                mov al,0
                mov ds:,al;显示后清除数据以免错乱
      add si,2
                inc di
               
      loop show_s1
show_s0:pop dx
                pop si
                pop cx
                pop bx
                pop di
                ret 6
;源码终



codesg ends
endstart
页: [1]
查看完整版本: 程序设计一,字符写入问题,求大神告知下