第十章课程设计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-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 22:19 static/image/common/back.gif
为什么我发的提问帖都没人答的????各位就算不想看代码 也可分析下啊或者直接拷到电脑上调试也可啊
...
额,我还没学到这里,正在排版中,看看能不能帮上你{:5_109:} 我看看先、太长了没兴趣看完、、 堆栈传送时出错:bx=3520h
你在call putchar的时候dx并不等于你的列号 测试结果是:dx=0600h
divdw不保护dx,一保护就触发dtoc中的异常,然后死循环
堆栈传数,不想看了 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 函数有问题吗??就是你将的保护我实在是笨看不懂麻烦详细点 谢谢了 jkiok 发表于 2013-10-22 12:07 static/image/common/back.gif
朋友 能将详细点吗 ???不太懂你将什么??我菜鸟啊 divdw不保护dx是将函数体没有对它进行压栈??还是 ...
请尽量避免使用栈来存放临时数据,因为这种导致错误是很难分析的
可以在ds中划出一块作为缓冲区
还有就是你的putchar函数真的是:dizzy:
我这里有可移植的show_str函数
我尝试了一下用我的函数来操作,把它临时改为putchar(修改了一行,因为我的默认输入是bx)
结果在附件,几乎没有问题。
建议思考一下一个完整可移植的show_str函数。
另:看你的代码好累啊{:5_109:},要不是今天无聊、、
如果需要的话我可以贴出来:)当然如果你能思考一下当然更好了 chenhi 发表于 2013-10-22 12:40 static/image/common/back.gif
请尽量避免使用栈来存放临时数据,因为这种导致错误是很难分析的
可以在ds中划出一块作为缓冲区
还有就 ...
谢谢 我很菜的 刚学习没多久 那个putchar是真的很烂主要是开始想用栈做临时变量 后来发现不好用(c语言影响) 还有个不请之请 就是putchar函数里面有 sub sp,20实际用不到20byte 但是我把它改成3byte(里面只用到3个)时就出错 不知道为什么 实在谢谢能不能把你的show_str 贴出来??谢谢 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:代码读懂很有帮助哦~ 英文调试器拷不出中文。。对照你以前的看好了、、我的没加注释,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:08 static/image/common/back.gif
英文调试器拷不出中文。。对照你以前的看好了、、我的没加注释,show_str加了:)
超长了、、分开来{:1_1:} chenhi 发表于 2013-10-22 13:09 static/image/common/back.gif
超长了、、分开来
感谢 能交个朋友吗?? 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一般够用了) jkiok 发表于 2013-10-22 13:14 static/image/common/back.gif
感谢 能交个朋友吗??
{:1_1:}能啊,不过我有时差、、睡觉去了:sleepy:
页:
[1]