鱼C论坛

 找回密码
 立即注册
查看: 1939|回复: 2

[已解决]程序设计一,字符写入问题,求大神告知下

[复制链接]
发表于 2017-1-10 04:29:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
问题: 程序设计一,为何在指定长度写入的数据还会导致文字错乱? 代码如下:
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:[bx]                
                mov word ptr ds:[si],ax
                
                mov ax,word ptr ss:[bx].2
                mov word ptr ds:[si].2,ax ;年份装入ds:si中
                add si,6
                
                push dx
                mov ax, word ptr ss:[bx].54h
                push ax
                mov ax, word ptr ss:[bx].56h
                push ax
                mov ax,0ah
                push ax
                call dtoc ;收入转入ds:si
                add si,6
                
                mov ax,word ptr ss:[di].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:[bx].54h
                push ax
                mov ax, word ptr ss: [bx].56h
                push ax
                mov ax,word ptr ss:[di].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,[bp+2]
e:                push cx
                mov cl,ds:[si]
                jcxz b
c:                inc si
                pop cx
                loop e
                mov al,0
                mov ds:[si],al
                pop cx
                ret 2
                
b:                mov al,20h
                mov ds:[si],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,[bp+0ch] ;(ax)
                mov dx,[bp+0ah] ;(dx)
dtocs:        mov cx,[bp+8] ;型数据,如果除数为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:[si],al ;写入[ds:si]中
                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,[bp+6] ;高16位数据
                mov dx,0
                mov cx,[bp+4]
                div cx      
                mov si,ax
                mov ax,[bp+8]
                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,[bp+12h]
                mov ds,ax
                mov ax,0b800h  ;屏幕显示地址
        mov es,ax
                mov ax,[bp+0eh] ;行
                
                add ax,4 
        mov bx,160   ;第一行4*160
                mul bx
        mov bx,ax        
        mov si,[bp+0ch]
                mov di,0
show_s1:mov cl,ds:[di]     ;ds:[di]指向文本byte单元                 
                mov ch,0  
        jcxz show_s0;如果=0直接返回
                mov ch,[bp+10h]      ;颜色
        mov es:[bx][si],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
end  start
最佳答案
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:[bx]                
                mov word ptr ds:[si],ax
                
                mov ax,word ptr ss:[bx].2
                mov word ptr ds:[si].2,ax ;年份装入ds:si中
                add si,6
                
                push dx ;入栈显示行
                mov ax, word ptr ss:[bx].54h
                push ax
                mov ax, word ptr ss:[bx].56h
                push ax
                call dtoc ;收入转入ds:si
                add si,8
                
                mov ax,word ptr ss:[di].0a8h
                push ax
                mov ax,0
                push ax
                call dtoc ;人员转入ds:si中
                add si,4
                
                
                push cx ;入栈cx,保存循环次数
                mov ax, word ptr ss:[bx].54h
                push ax
                mov ax, word ptr ss: [bx].56h
                push ax
                mov cx,word ptr ss:[di].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,[bp+2] ;将长度赋值给cx
e:                push cx  ;保存长度
                mov cl,ds:[si]  ;获取ds:si字符
                jcxz b   ;是否为零,如果为零调到b,进行转为空格
c:                inc si   ;不为零,ds:si 指向下一个字符
                pop cx   ;取出cx,
                loop e
                mov al,0
                mov ds:[si],al;字符串以0结尾
                pop cx
                ret 2                
b:                mov al,20h
                mov ds:[si],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,[bp+0ah] ;(ax)
                mov dx,[bp+08h] ;(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:[si],al ;写入[ds:si]中
                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,[bp+4] ;高16位数据
                mov dx,0
                div cx      
                mov si,ax  ;保存高位商
                mov ax,[bp+6] ;低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,[bp+0eh] ;行                
                add ax,4 
        mov bx,160   ;第一行4*160
                mul bx
        mov bx,ax        
        mov si,[bp+0ch] ;列
                mov di,0
show_s1:mov cl,ds:[di]     ;ds:[di]指向文本byte单元                 
                mov ch,0  
        jcxz show_s0;如果=0直接返回
                mov ch,[bp+10h]      ;颜色
        mov es:[bx][si],cx ;显示
                mov al,0
                mov ds:[di],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
end  start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 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,[bp+0ch] ;(ax)
                mov dx,[bp+0ah] ;(dx)
dtocs:        mov cx,[bp+8] ;型数据,如果除数为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,[bp+8],错位了.用另外一个寄存器保存下被除数就好了.
                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:[si],al ;写入[ds:si]中
                inc si
                loop dtoct
                pop cx        
                pop di
                pop dx
                ret 6
;源码终

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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:[bx]                
                mov word ptr ds:[si],ax
                
                mov ax,word ptr ss:[bx].2
                mov word ptr ds:[si].2,ax ;年份装入ds:si中
                add si,6
                
                push dx ;入栈显示行
                mov ax, word ptr ss:[bx].54h
                push ax
                mov ax, word ptr ss:[bx].56h
                push ax
                call dtoc ;收入转入ds:si
                add si,8
                
                mov ax,word ptr ss:[di].0a8h
                push ax
                mov ax,0
                push ax
                call dtoc ;人员转入ds:si中
                add si,4
                
                
                push cx ;入栈cx,保存循环次数
                mov ax, word ptr ss:[bx].54h
                push ax
                mov ax, word ptr ss: [bx].56h
                push ax
                mov cx,word ptr ss:[di].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,[bp+2] ;将长度赋值给cx
e:                push cx  ;保存长度
                mov cl,ds:[si]  ;获取ds:si字符
                jcxz b   ;是否为零,如果为零调到b,进行转为空格
c:                inc si   ;不为零,ds:si 指向下一个字符
                pop cx   ;取出cx,
                loop e
                mov al,0
                mov ds:[si],al;字符串以0结尾
                pop cx
                ret 2                
b:                mov al,20h
                mov ds:[si],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,[bp+0ah] ;(ax)
                mov dx,[bp+08h] ;(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:[si],al ;写入[ds:si]中
                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,[bp+4] ;高16位数据
                mov dx,0
                div cx      
                mov si,ax  ;保存高位商
                mov ax,[bp+6] ;低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,[bp+0eh] ;行                
                add ax,4 
        mov bx,160   ;第一行4*160
                mul bx
        mov bx,ax        
        mov si,[bp+0ch] ;列
                mov di,0
show_s1:mov cl,ds:[di]     ;ds:[di]指向文本byte单元                 
                mov ch,0  
        jcxz show_s0;如果=0直接返回
                mov ch,[bp+10h]      ;颜色
        mov es:[bx][si],cx ;显示
                mov al,0
                mov ds:[di],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
end  start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-25 13:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表