鱼C论坛

 找回密码
 立即注册
查看: 2621|回复: 14

实验10答案中的一个问题

[复制链接]
发表于 2013-8-13 01:48:06 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 小咒 于 2013-8-13 01:58 编辑

课题要求:
名称:show_str
功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
参数:(dh)=行号(取值范围0~24);
(dl)=列号(取值范围0~79);
(cl)=颜色;
ds:si指向字符串的首地址。
返回:无。


想问一个问题,首先我们的要求是一个show_str的子程序来控制指定位置指定颜色的写入,0来表示结束
在课题的答案中会把ax bx si es进行一个push入栈,当子程序结束后把他们pop出栈然后再进行一个ret
这个操作我就不是很明白为什么这里要把这几个值push入栈呢?


自己代码如下:
assume cs:code,ds:data
data segment
db 'Welcome to masm!',0
data ends

code segment
start:
mov dh,8;行号
mov dl,3;列号
mov cl,2;颜色
mov ax,data
mov ds,ax
mov si,0
call show_str

mov ax,4c00h
int 21h
;段地址b8000h-b80a0第一行
show_str:mov ax,0b800h
mov es,ax;段地址放入es
mov ax,0a0h;计算行号
mul dh;计算段地址
mov bx,ax;段地址放入bx
mov ax,2h;计算列号
mul dl;计算列号
add bx,ax;bx指向偏移地址[行号列号数据]
mov ah,cl;颜色放入ah
mov ch,00h

s:mov cl,[si]
jcxz s0
mov al,cl
mov es:[bx],ax
inc si
add bx,2
jmp s;无条件跳转

s0:ret;取栈顶值放入ip 返回

code ends
end start
答案代码:
assume cs:code,ds:data
data segment
     db 'welcome to masm!',0
data ends

code segment
start:   mov dh,8
     mov dl,3
     mov cl,2
     mov ax,data
     mov ds,ax
     mov si,0
     call show_str

     mov ax,4c00h
     int 21h

;名称:show_str
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24);
;      (dl)=列号(取值范围0~79);
;      (cl)=颜色;
;      ds:si指向字符串的首地址。
;返回:无。

show_str:
     push ax
     push bx
     push es
     push si
     mov ax,0b800h
     mov es,ax
     mov ax,160
     mul dh
     mov bx,ax ;bx=160*dh
     mov ax,2
     mul dl        ;ax=dl*2
     add bx,ax     ;mov bx,(160*dh+dl*2)设置es:bx指向显存首地址
     mov al,cl     ;把颜色cl赋值al
     mov cl,0

show0:
     mov ch,[si]
     jcxz show1    ;(ds:si)=0时,转到show1执行    
     mov es:[bx],ch
     mov es:[bx].1,al
     inc si        ;ds:si指向下一个字符地址
     add bx,2      ;es:bx指向下一个显存地址
     jmp show0

show1:
     pop si
     pop es
     pop bx
     pop ax
     ret

code ends
end start




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

使用道具 举报

发表于 2013-8-13 05:56:38 | 显示全部楼层
我想我这么回答你 比如CALL 要完成一个函数的调用 汇编不是会先自右向左吧函数的参数压栈吗等到调用时在出栈便是自左向右 栈是一个暂时存储数据的地方 这些参数一般都是压栈的
我也刚刚学到第十章 希望能帮到你如有错误望请见谅
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-13 06:33:21 | 显示全部楼层

你说的这个意思我理解,但是答案中的是调用时把它们push入栈了,调用过后pop出栈了
而并非需要调用时才pop出栈
所以我才对这里的代码有疑问,要不就是我对代码的理解错误?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-8-13 06:38:35 | 显示全部楼层
小咒 发表于 2013-8-13 06:33
你说的这个意思我理解,但是答案中的是调用时把它们push入栈了,调用过后pop出栈了
而并非需要调用时才p ...

但是答案中的是调用时把它们push入栈了,调用过后pop出栈了
压栈的数据使用过后当然要出栈啊 否则程序一大你需要多少个栈啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-13 06:45:46 | 显示全部楼层
牡丹花下死做鬼 发表于 2013-8-13 06:38
但是答案中的是调用时把它们push入栈了,调用过后pop出栈了
压栈的数据使用过后当然要出栈啊 否则程序一 ...

但是这个子程序中没有运用到任何的栈内数据,子程序中没有任何的出栈操作,相对于这个子程序而言,这样的入栈和出栈的操作不就变得没有意义?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-8-13 06:49:49 | 显示全部楼层
小咒 发表于 2013-8-13 06:45
但是这个子程序中没有运用到任何的栈内数据,子程序中没有任何的出栈操作,相对于这个子程序而言,这样的 ...
 pop si
     pop es
     pop bx
     pop ax
     ret
这个不是出栈吗
push ax
     push bx
     push es
     push si
这个不是入栈吗
其实这代码 我前几天学的时候也没怎么看(*^__^*) 嘻嘻…… 应为学习汇编是为了理解C和学解密所以对这个
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-13 06:57:27 | 显示全部楼层
牡丹花下死做鬼 发表于 2013-8-13 06:49
这个不是出栈吗这个不是入栈吗
其实这代码 我前几天学的时候也没怎么看(*^__^*) 嘻嘻…… 应为学习汇编是 ...

不是呀,你仔细看代码,我说的意思是这个入栈和出栈的操作在子程序中没有调用栈内数据,所以我认为对于这个子程序而言这个入栈和出栈的操作是没有意义的
以高级语言来编译程序我知道调用过程中先把参数push入栈有需要才会把参数pop出来,用完后再push进去
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-8-13 07:10:32 | 显示全部楼层
小咒 发表于 2013-8-13 06:57
不是呀,你仔细看代码,我说的意思是这个入栈和出栈的操作在子程序中没有调用栈内数据,所以我认为对于这 ...

介个......  恕我以目前的知识 无法解释  sorry~~~~(>_<)~~~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-13 07:47:25 | 显示全部楼层
牡丹花下死做鬼 发表于 2013-8-13 07:10
介个......  恕我以目前的知识 无法解释  sorry~~~~(>_

嗯,共同努力进步吧,估计也就我对这个有疑问而已
不知道这个答案是不是王爽老师自己写的,如果是的话我感觉他是想让我们更了解栈的原理,另外因为运用到call与ret也有对栈进行操作,所以给我们加深理解。
没有更好的解释的话我只能这样自行理解了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-8-13 07:56:25 | 显示全部楼层
小咒 发表于 2013-8-13 07:47
嗯,共同努力进步吧,估计也就我对这个有疑问而已
不知道这个答案是不是王爽老师自己写的,如果是的话我 ...

是啊 一起努力吧 只可惜快要暂离鱼C了 变成苦逼的高二党
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-8-13 08:38:31 | 显示全部楼层
      楼主~!其实这个问题很简单啊,你想想如果一个程序要调用很多子程序,而且每个子程序里用到的寄存器都有差不多你怎么办,所以要在调用子程序之前先把先把相关的寄存器的值保存,调用完后再恢复,方便下个要调用的子程序取值。这跟C的调用函数差不多吧,所以养成这种习惯对以后学习有帮助的。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-13 08:40:39 | 显示全部楼层
牡丹花下死做鬼 发表于 2013-8-13 07:56
是啊 一起努力吧 只可惜快要暂离鱼C了 变成苦逼的高二党

不错了高1的时候就有那么强的求知欲望,慢慢努力到大学了必成大器哟
我高1的时候还只会玩游戏呢,咱都已经是快要结婚的人了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-7-6 12:29:02 | 显示全部楼层
我想这应该是让我们形成一种习惯,保证用到的寄存器都恢复过来,不过如果这样理解的话,DX寄存器也应压栈再POP,因为里面用到了DH。

一个程序可能不止一个子程序,如果存在多个子程序调用到寄存器的行为,在子程序前都压栈,结束前都出栈,这样就不会影响到其他子程序对寄存器的使用,结果发生错误的几率将大大减少。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-26 17:31:30 | 显示全部楼层
不知道为什么用debug调试说内存指令出错,但直接在cmd下运行程序就好好的,没有任何问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-8-26 17:47:54 | 显示全部楼层
答案的代码里面用到了ch,但是事先并没有保存,为什么不直接push cx顺便保存一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-27 00:50

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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