鱼C论坛

 找回密码
 立即注册
查看: 2886|回复: 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入栈呢?


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

  5. code segment
  6. start:
  7. mov dh,8;行号
  8. mov dl,3;列号
  9. mov cl,2;颜色
  10. mov ax,data
  11. mov ds,ax
  12. mov si,0
  13. call show_str

  14. mov ax,4c00h
  15. int 21h
  16. ;段地址b8000h-b80a0第一行
  17. show_str:mov ax,0b800h
  18. mov es,ax;段地址放入es
  19. mov ax,0a0h;计算行号
  20. mul dh;计算段地址
  21. mov bx,ax;段地址放入bx
  22. mov ax,2h;计算列号
  23. mul dl;计算列号
  24. add bx,ax;bx指向偏移地址[行号列号数据]
  25. mov ah,cl;颜色放入ah
  26. mov ch,00h

  27. s:mov cl,[si]
  28. jcxz s0
  29. mov al,cl
  30. mov es:[bx],ax
  31. inc si
  32. add bx,2
  33. jmp s;无条件跳转

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

  35. code ends
  36. end start
复制代码

答案代码:
  1. assume cs:code,ds:data
  2. data segment
  3.      db 'welcome to masm!',0
  4. data ends

  5. code segment
  6. start:   mov dh,8
  7.      mov dl,3
  8.      mov cl,2
  9.      mov ax,data
  10.      mov ds,ax
  11.      mov si,0
  12.      call show_str

  13.      mov ax,4c00h
  14.      int 21h

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

  22. show_str:
  23.      push ax
  24.      push bx
  25.      push es
  26.      push si
  27.      mov ax,0b800h
  28.      mov es,ax
  29.      mov ax,160
  30.      mul dh
  31.      mov bx,ax ;bx=160*dh
  32.      mov ax,2
  33.      mul dl        ;ax=dl*2
  34.      add bx,ax     ;mov bx,(160*dh+dl*2)设置es:bx指向显存首地址
  35.      mov al,cl     ;把颜色cl赋值al
  36.      mov cl,0

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

  45. show1:
  46.      pop si
  47.      pop es
  48.      pop bx
  49.      pop ax
  50.      ret

  51. code ends
  52. end start
复制代码





小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

使用道具 举报

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

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

使用道具 举报

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

但是答案中的是调用时把它们push入栈了,调用过后pop出栈了
压栈的数据使用过后当然要出栈啊 否则程序一大你需要多少个栈啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

但是这个子程序中没有运用到任何的栈内数据,子程序中没有任何的出栈操作,相对于这个子程序而言,这样的入栈和出栈的操作不就变得没有意义?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

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

使用道具 举报

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

介个......  恕我以目前的知识 无法解释  sorry~~~~(>_<)~~~~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

是啊 一起努力吧 只可惜快要暂离鱼C了 变成苦逼的高二党
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

不错了高1的时候就有那么强的求知欲望,慢慢努力到大学了必成大器哟
我高1的时候还只会玩游戏呢,咱都已经是快要结婚的人了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-16 10:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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