jkiok 发表于 2013-10-21 16:00:04

第十章课程设计1 问题(很诡异。。。)求解答


很无语单独调试显示“人均收入”函数没问题,但把另外三条函数加上去就不能显示另外三条函数也是没问题的(单独调试)
好像两者水火不相容一样,我也看过条用每条函数后寄存器的变化了 都正常的 条用后都没改变寄存器值真是见鬼了我 求大神啊
贴上源码assume cs:code,ds:data,ss:stack怎么用上面那个贴源码?????算了 直接贴assume cs:code,ds:data,ss:stack

data segment        ;数据段
        string db 11 dup (0)        ;字符串数据缓冲区
        year   db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
                   db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
                   db '1993','1994','1995'
        ;以上为年份
        summ   dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
                   dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000
                   dd 5947000
        ;以上为收入
        people dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635
                   dw 8226,11452,14430,15257,17800
        ;以上为人员数
data ends

stack segment        ;栈空间段
        db 1000 dup (0)
stack ends

code segment        ;代码段
start:                           mov ax,stack
                                mov ss,ax
                                mov sp,1000
                                mov ax,data
                                mov ds,ax
                               
                                call clear_asm        ;清屏                               
                                ;call show_year        ;显示年份                       
                                ;call show_people;显示员工
                                ;call show_summ        ;显示年收入
                                call show_Average;显示人均收入                                       
                                ;???为什么只调用此函数可以正常显示
                                ;加上上面三条显示年份、员工、收入后就不显示了??
                               
                                mov ax,4c00h
                                int 21h

;---------------------------------------------------------------
        ;函数功能:排版并显示人均收入
        ;函数参数:无
        ;函数返回:无
show_Average:       
                                push ax
                                push bx
                                push cx
                                push dx
                                push si
                                push di
                                push bp

                                mov si,0                ;指向字符串数据缓冲区
                                mov bx,95                ;指向年收入
                                mov di,179                ;指向员工数                               
                                mov dx,054Bh    ;行号及列号
                               
                                mov cx,21
Average_start:        push cx
                                push dx
                                mov ax,ds:        ;获取年收入
                                mov dx,ds:
                                mov cx,ds:        ;获取员工数
                                call divdw                ;计算均值
                                call dtoc                ;转为字符串                               
                                pop dx
                                mov cl,04h                ;数据显示属性
                                call putchars        ;显示数据
                                inc dh                        ;行号加一
                                add bx,4                ;指向下一个收入数据
                                add di,2                ;指向下一个员工数据
                                pop cx
                                loop Average_start
                               
                                pop bp
                                pop di
                                pop si
                                pop dx
                                pop cx
                                pop bx
                                pop ax
                                ret
                               
;-----------------------------------------------------------------
        ;函数功能:排版并显示员工数
        ;函数参数:无       
        ;函数返回:无
show_people:
                                push ax
                                push bx
                                push cx
                                push dx
                                push si
                                push bp
                                sub sp,1
                                mov bp,sp
                               
                                mov byte ptr ss:,5;初始化开始显示行号
                                mov bx,179;指向员工数据开始偏移量处
                               
                                mov cx,21                ;
people_start:        push cx
                                mov ax,        ;获取数据
                                mov dx,0
                                mov si,0       ;指向字符串数据缓冲区
                                call dtoc                ;数据转换
                               
                                mov dh,ss:;数据显示行号
                                mov dl,50                ;数据列号
                                mov cl,04h                ;数据显示属性
                                call putchars        ;显示数据       
                                push ax
                                mov al,ss:        ;行号加一
                                inc al
                                mov ss:,al
                                pop ax
                                add bx,2                ;指向下一个数据
                                pop cx
                                loop people_start
                               
                                add sp,1
                                pop bp
                                pop si
                                pop dx
                                pop cx
                                pop bx
                                pop ax
                                ret                               
                               
                       
                               
;-------------------------------------------------------------------
        ;函数功能:排版并显示年收入
        ;函数参数:无
        ;函数返回:无
        show_summ:       
                                push ax
                                push bx
                                push cx
                                push dx
                                push si
                                push bp
                                sub sp,1
                                mov bp,sp
                               
                                mov byte ptr ss:,5;初始化开始显示行号
                                mov bx,95;指向收入数据开始偏移量处
                               
                                mov cx,21                ;
        summ_start:        push cx
                                mov ax,        ;获取数据低16位
                                mov dx,;获取数据高16位
                                mov si,0       ;指向字符串数据缓冲区
                                call dtoc                ;数据转换
                               
                                mov dh,ss:;数据显示行号
                                mov dl,25                ;数据列号
                                mov cl,04h                ;数据显示属性
                                call putchars        ;显示数据       
                                push ax
                                mov al,ss:        ;行号加一
                                inc al
                                mov ss:,al
                                pop ax
                                add bx,4                ;指向下一个数据
                                pop cx
                                loop summ_start
                               
                                add sp,1
                                pop bp
                                pop si
                                pop dx
                                pop cx
                                pop bx
                                pop ax
                                ret
;-------------------------------------------------------------------
        ;函数功能:清屏
        ;函数参数:无
        ;函数返回:无
        clear_asm:        push bx
                                push cx
                                push ds
                                push ax
       
                                mov ax,0b800h
                                mov ds,ax
                                xor bx,bx
                               
                                mov cx,2000                               
        clear_start:mov word ptr ,0
                                add bx,2
                                loop clear_start
                               
                                pop ax
                                pop ds
                                pop cx
                                pop bx
                                ret
                               
;--------------------------------------------------------------------
        ;函数功能:排版年份并显示
        ;函数参数:无
        ;函数返回:无
        show_year:        push dx
                                push ax
                                push cx
                                push di
                                push si
                                push bp                               
                                sub sp,3
                                mov bp,3
                               
                                mov word ptr ss:,11                ;年份开始偏移量
                                mov byte ptr ss:,5        ;显示开始行号
                                mov cx,21                ;显示年份
        year_start:        push cx                        ;保存循环次数
                                mov si,0                   ;数据copy开始偏移量
                                mov di,ss:        ;原数据地址       
                                mov ax,4                ;copy数量
                                call strings_copy;字符串拷贝                                                               
                                mov dh,ss:;数据显示行号
                                mov dl,0                ;数据列号
                                mov cl,04h                ;数据显示属性
                                call putchars        ;显示数据       
                                push ax
                                mov ax,ss:        ;获取年份开始偏移量
                                add ax,4                ;指向下一年
                                mov ss:,ax
                                mov al,ss:;获取显示开始行号
                                inc al
                                mov ss:,al;指向下一行
                                pop ax
                                pop cx
                                loop year_start
                               
                                add sp,3
                                pop bp
                                pop si
                                pop di
                                pop cx
                                pop ax
                                pop dx
                                ret
                                                       
;-----------------------------------------------------------------------                               
        ;函数功能:进行字符串拷贝并在字符串尾填0
        ;函数参数:ax=要拷贝的数据长度 ds:di=数据开始地址 ds:si=数据拷贝后地址
        ;函数返回:无
strings_copy:        push ax
                                push cx
                                push di
                                push si
                               
                                mov cx,ax
        copy_start:        mov al,ds:
                                mov ds:,al
                                inc di
                                inc si
                                loop copy_start
                                mov byte ptr ds:,0
                               
                                pop si
                                pop di
                                pop cx
                                pop ax
                                ret
                                                                              
;--------------------------------------------------------------------                               
        ;函数功能:在指定位置打印指定字符串
        ;参数:dh行号 dl列号 cl颜色 ds:si指向字符串的首地址
        ;函数返回:无
        putchars:        push bp
                                push ax
                                push bx
                                push cx
                                push dx
                                push si
                                push di
                                push es
                                sub sp,20
                                mov bp,sp       
                               
                                mov ax,0b800h        ;获取显存段地址
                                mov es,ax
                                xor ax,ax
                                mov al,dh                ;获取行号
                                sub al,1
                                add dl,dl
                                mov byte ptr ss:,dl;获取列号
                                mov bx,160               
                                mul bx
                                add ax,ss:                ;获取偏移地址
                                mov word ptr ss:,ax
                                                       
                                mov al,cl        ;获取颜色
                                xor cx,cx
                               
                                mov di,0
                                mov bx,0
        xie_char:        mov cl,ds:;获取字符
                                jcxz put_return
                                push bx
                                mov bx,ss:
                                mov byte ptr es:,cl        ;写字符
                                mov byte ptr es:,al        ;写颜色
                                add di,2
                                pop bx
                                inc bx
                                jmp xie_char
                               
        put_return:        add sp,20
                                pop es
                                pop di
                                pop si
                                pop dx
                                pop cx
                                pop bx
                                pop ax
                                pop bp
                                ret       
;---------------------------------------------------------------------
        ;函数功能:进行无溢出的除法运算16Bit
        ;函数参数:ax=dword数据的低16位 dx=dword数据高16位 cx=除数
        ;函数返回:dx=结果高16位 ax=结果低16位 cx=余数
        divdw:                push bp
                                push bx       
                                sub sp,2
                                mov bp,sp
                               
                                mov ss:,ax;存放被除数低16位
                               
                                mov ax,dx
                                xor dx,dx                               
                                div cx
                                mov bx,ax        ;存放结果高16位
                               
                                mov ax,ss:
                                div cx
                                mov cx,dx                        ;获取余数
                                mov dx,bx        ;获取高16位
                               
                                add sp,2
                                pop bx
                                pop bp
                                ret
                               
;------------------------------------------------------------------------
        ;函数功能:32Bit整形数据转为字符串
        ;函数参数: ax数据低16位 dx数据高16位 及存放字符串的 ds:si 地址
        ;函数返回:无
        dtoc:                push ax
                                push bx
                                push cx
                                push dx
                                push si
                                push di
                               
                                xor di,di        ;用于字符串计数器 先清零
                               
        dtoc_start:        mov cx,10
                                call divdw
                                mov bx,cx        ;获取余数                               
                                mov cx,dx
                                jcxz sizo1        ;检查高16位是否为零
                int_OK:        add bx,30h        ;转为ASCLL码
                                push bx                ;压栈
                                inc di                ;计算字符大小
                                jmp dtoc_start       
       
                sizo1:        mov cx,ax       
                                jcxz sizo2        ;检查低16位是否为零
                                jmp int_OK
                               
                sizo2:        mov cx,bx        ;检查余数是否为零
                                jcxz sizo3
                                jmp int_OK
                               
                sizo3:        mov cx,di        ;获取字符大小
                pop_ch:        pop dx               
                                mov ds:,dl
                                inc si
                                loop pop_ch
                                mov byte ptr ds:,0        ;填充最后一个字符
                                               
                                pop di
                                pop si
                                pop dx
                                pop cx
                                pop bx
                                pop ax
                                ret
       
       
code ends
end start


求解答 谢谢



chenhi 发表于 2013-10-21 16:00:05

本帖最后由 chenhi 于 2013-10-22 13:26 编辑

show_str:调用方法:      mov dh, 1      ;行号 1-25
      mov dl, 1      ;列号 1-80
      mov cl, 7      ;字体颜色 白色:7 蓝色:1 绿色:2 红色:4
      mov bx, 0      ;自定义数据将在data段中的开始位置,从零开始show_str:实现过程:show_str:                ;字符串默认在ds寄存器中
      push bx
                push ax
                        push dx
                              push cx
                                        push si
                                                push di
                                                      push es
                                                                push si
                                                                        push cx
                                                                              dec dh
                                                                              dec dl
                                                                              xor di, di
                                                                              xor cx, cx
                                                                              mov cl, dh
                                                                              mov ax, 0b800h
                                                                              jcxz cx0
                                                                              s:
                                                                                        push cx
                                                                                                mov cx, ax
                                                                                                add cx, 0ah
                                                                                                mov ax, cx
                                                                                        pop cx
                                                                              loop s
                                                                              
                                                                              cx0:
                                                                              mov es, ax
                                                                              
                                                                              push dx
                                                                                        add dl, dl
                                                                                        xor dh, dh
                                                                                        mov di, dx
                                                                              pop dx
                                                                        pop cx
                                                                pop si      
                                                                xor si, si
                                                                s1:
                                                                        push cx
                                                                              push ax
                                                                                        mov al,
                                                                                        mov byte ptr es:, al
                                                                                        inc di
                                                                                        mov es:, cl
                                                                                        inc si
                                                                                        inc di
                                                                                        xor cx, cx
                                                                                        mov cl,
                                                                                        jcxz s2                ;一旦执行会直接跳过pop cx导致栈错乱,所以在s2开始处就应pop cx
                                                                              pop ax
                                                                        pop cx
                                                                jmp s1
                                                               
                                                                s2:
                                                                              pop ax
                                                                        pop cx
                                                               
                                                      pop es
                                                pop di
                                        pop si
                              pop cx
                        pop dx
                pop ax
      pop bx
      
      ret      附件是我改完代码的输出。{:1_1:}实现代码在13楼和18楼:ton:

jkiok 发表于 2013-10-21 18:29:06

怎么没人啊大家把源码考到电脑下运行下也好啊求解答

随风听雨雪 发表于 2013-10-21 21:04:13

看了,但是不懂

jkiok 发表于 2013-10-21 22:19:40

为什么我发的提问帖都没人答的????各位就算不想看代码 也可分析下啊或者直接拷到电脑上调试也可啊

再次感谢了

LinuxDeepin 发表于 2013-10-21 22:21:44

jkiok 发表于 2013-10-21 22:19 static/image/common/back.gif
为什么我发的提问帖都没人答的????各位就算不想看代码 也可分析下啊或者直接拷到电脑上调试也可啊
...

额,我还没学到这里,正在排版中,看看能不能帮上你{:5_109:}

chenhi 发表于 2013-10-22 07:50:14

我看看先、太长了没兴趣看完、、

chenhi 发表于 2013-10-22 09:06:13

堆栈传送时出错:bx=3520h
你在call putchar的时候dx并不等于你的列号 测试结果是:dx=0600h
divdw不保护dx,一保护就触发dtoc中的异常,然后死循环
堆栈传数,不想看了

jkiok 发表于 2013-10-22 12:07:54

chenhi 发表于 2013-10-22 09:06 static/image/common/back.gif
堆栈传送时出错:bx=3520h
你在call putchar的时候dx并不等于你的列号 测试结果是:dx=0600h
divdw不保护 ...

朋友 能将详细点吗 ???不太懂你将什么??我菜鸟啊 divdw不保护dx是将函数体没有对它进行压栈??还是什么??dx在这里是要传递参数的 返回值也是放到dx中的 所以没有进行压栈栈传递出错??在什么地方??call putchars 函数有问题吗??就是你将的保护我实在是笨看不懂麻烦详细点 谢谢了

chenhi 发表于 2013-10-22 12:40:35

jkiok 发表于 2013-10-22 12:07 static/image/common/back.gif
朋友 能将详细点吗 ???不太懂你将什么??我菜鸟啊 divdw不保护dx是将函数体没有对它进行压栈??还是 ...

请尽量避免使用栈来存放临时数据,因为这种导致错误是很难分析的
可以在ds中划出一块作为缓冲区
还有就是你的putchar函数真的是:dizzy:
我这里有可移植的show_str函数
我尝试了一下用我的函数来操作,把它临时改为putchar(修改了一行,因为我的默认输入是bx)
结果在附件,几乎没有问题。
建议思考一下一个完整可移植的show_str函数。
另:看你的代码好累啊{:5_109:},要不是今天无聊、、
如果需要的话我可以贴出来:)当然如果你能思考一下当然更好了

jkiok 发表于 2013-10-22 12:53:51

chenhi 发表于 2013-10-22 12:40 static/image/common/back.gif
请尽量避免使用栈来存放临时数据,因为这种导致错误是很难分析的
可以在ds中划出一块作为缓冲区
还有就 ...

谢谢 我很菜的 刚学习没多久 那个putchar是真的很烂主要是开始想用栈做临时变量 后来发现不好用(c语言影响) 还有个不请之请 就是putchar函数里面有 sub sp,20实际用不到20byte 但是我把它改成3byte(里面只用到3个)时就出错 不知道为什么 实在谢谢能不能把你的show_str 贴出来??谢谢   

chenhi 发表于 2013-10-22 13:01:43

jkiok 发表于 2013-10-22 12:53 static/image/common/back.gif
谢谢 我很菜的 刚学习没多久 那个putchar是真的很烂主要是开始想用栈做临时变量 后来发现不好用(c语 ...

16位寄存器每次推栈两个字节,建议多空一两个byte,因为栈指针的规则很麻烦,懒得烦心就留一个byte
我分开来贴把,我刚刚改了一下你的show_year,就是最简单的改了一改,输出是完全正确的了。
下一楼我贴我帮你改完的,就改了show_year的方式和一点点show_str的参数,别的实在是懒得看了、、
再下楼我贴show_str的原版+调用方法:titter:代码读懂很有帮助哦~

chenhi 发表于 2013-10-22 13:08:05

英文调试器拷不出中文。。对照你以前的看好了、、我的没加注释,show_str加了:)
;Edited by chenhi
;you can erase it:)
;OCT 22ND 2013
assume cs:code,ds:data,ss:stack
data segment      ;êy¾Y¶Î
      string db 11 dup (0)      ;×Ö·û′®êy¾Y»o3åÇø
      year   db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
                   db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
                   db '1993','1994','1995'
      ;òÔéÏÎaÄê·Y
      summ   dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
                   dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000
                   dd 5947000
      ;òÔéÏÎaêÕèë
      people dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635
                   dw 8226,11452,14430,15257,17800
      ;òÔéÏÎaèËÔ±êy
data ends

stack segment      ;Õ»¿Õ¼ä¶Î
      db 1000 dup (0)
stack ends

code segment      ;′úÂë¶Î
start:                        mov ax,stack
                              mov ss,ax
                              mov sp,1000
                              mov ax,data
                              mov ds,ax
                              
                              call clear_asm      ;ÇåÆá                              
                              call show_year      ;ÏÔê¾Äê·Y                        
                              call show_people;ÏÔê¾Ô±1¤
                              call show_summ      ;ÏÔê¾ÄêêÕèë
                              call show_Average;ÏÔê¾è˾ùêÕèë                                       


                              mov ax,4c00h
                              int 21h

;---------------------------------------------------------------
      ;oˉêy1|Äü£oÅÅ°æ2¢ÏÔê¾è˾ùêÕèë
      ;oˉêy2Îêy£oÎT
      ;oˉêy·μ»Ø£oÎT
show_Average:      
                              push ax
                              push bx
                              push cx
                              push dx
                              push si
                              push di
                              push bp

                              mov si,0                ;Ö¸Ïò×Ö·û′®êy¾Y»o3åÇø
                              mov bx,95                ;Ö¸ÏòÄêêÕèë
                              mov di,179                ;Ö¸ÏòÔ±1¤êy                              
                              mov dx,054Bh    ;DDoż°áDoÅ
                              
                              mov cx,21
Average_start:      push cx
                              push dx
                              mov ax,ds:      ;»ñè¡ÄêêÕèë
                              mov dx,ds:
                              mov cx,ds:      ;»ñè¡Ô±1¤êy
                              call divdw                ;¼ÆËã¾ùÖμ
                              call dtoc                ;×aÎa×Ö·û′®                              
                              pop dx
                              mov cl,04h                ;êy¾YÏÔê¾êôDÔ
                              call putchars      ;ÏÔê¾êy¾Y
                              inc dh                        ;DDożóò»
                              add bx,4                ;Ö¸ÏòÏÂò»¸öêÕèëêy¾Y
                              add di,2                ;Ö¸ÏòÏÂò»¸öÔ±1¤êy¾Y
                              pop cx
                              loop Average_start
                              
                              pop bp
                              pop di
                              pop si
                              pop dx
                              pop cx
                              pop bx
                              pop ax
                              ret
                              
;-----------------------------------------------------------------
      ;oˉêy1|Äü£oÅÅ°æ2¢ÏÔê¾Ô±1¤êy
      ;oˉêy2Îêy£oÎT      
      ;oˉêy·μ»Ø£oÎT
show_people:
                              push ax
                              push bx
                              push cx
                              push dx
                              push si
                              push bp
                              sub sp,1
                              mov bp,sp
                              
                              mov byte ptr ss:,5;3õê¼»ˉ¿aê¼ÏÔê¾DDoÅ
                              mov bx,179;Ö¸ÏòÔ±1¤êy¾Y¿aê¼Æ«òÆá¿′|
                              
                              mov cx,21                ;
people_start:      push cx
                              mov ax,      ;»ñè¡êy¾Y
                              mov dx,0
                              mov si,0         ;Ö¸Ïò×Ö·û′®êy¾Y»o3åÇø
                              call dtoc                ;êy¾Y×a»»
                              
                              mov dh,ss:;êy¾YÏÔê¾DDoÅ
                              mov dl,50                ;êy¾YáDoÅ
                              mov cl,04h                ;êy¾YÏÔê¾êôDÔ
                              call putchars      ;ÏÔê¾êy¾Y      
                              push ax
                              mov al,ss:      ;DDożóò»
                              inc al
                              mov ss:,al
                              pop ax
                              add bx,2                ;Ö¸ÏòÏÂò»¸öêy¾Y
                              pop cx
                              loop people_start
                              
                              add sp,1
                              pop bp
                              pop si
                              pop dx
                              pop cx
                              pop bx
                              pop ax
                              ret                              
                              
                        
                              

chenhi 发表于 2013-10-22 13:09:19

chenhi 发表于 2013-10-22 13:08 static/image/common/back.gif
英文调试器拷不出中文。。对照你以前的看好了、、我的没加注释,show_str加了:)

超长了、、分开来{:1_1:}

jkiok 发表于 2013-10-22 13:14:25

chenhi 发表于 2013-10-22 13:09 static/image/common/back.gif
超长了、、分开来

感谢 能交个朋友吗??

chenhi 发表于 2013-10-22 13:17:45

chenhi 发表于 2013-10-21 16:00 static/image/common/back.gif
show_str:调用方法:show_str:实现过程:附件是我改完代码的输出。

调用:call show_str(短距离)
(optional)call near ptr show_str(中距离call)
如果用到call far ptr,请自行改为retf(不建议, near一般够用了)

chenhi 发表于 2013-10-22 13:20:47

jkiok 发表于 2013-10-22 13:14 static/image/common/back.gif
感谢 能交个朋友吗??

{:1_1:}能啊,不过我有时差、、睡觉去了:sleepy:
页: [1]
查看完整版本: 第十章课程设计1 问题(很诡异。。。)求解答