王爽《汇编语言》检测点10.5的疑问

u010258183 2013-08-20 08:31:22
assume cs:code

stack segment
dw 8 dup (0)
stack ends

code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ds,ax
mov ax,0
call word ptr ds:[0EH]
inc ax
inc ax
inc ax

mov ax,4c00h
int 21h

code ends
end start

我用debug执行上面的代码,到call指令之前我看了一下ss:0e到0f之间的数据为77,0e。当call执行完了ss:0e到0f之间的数据变为11,00没错,但是现在call指令push ip后,ip的数据再会改为ds:[0EH]内存处的数据,因为ds==ss,所以ds:[0EH]即为ss:[0EH],但是ss:[0EH]处的数据为77,0e, 但是我d查看内存ip为什么是3302,而不是0e77或者是0011呢?
请高手们多多指点,谢谢了!
...全文
530 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
gbl959001 2014-04-22
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
这个代码不是这么看的,更不能用 debug 来单步什么的,而应该是单纯的静态分析,主要是针对堆栈的作用来的。如果用 debug 单步什么的话,会给堆栈写入内容导致 call 去了错误的地方,失去了这个代码设计的本来意义。 call word ptr ds:[0EH],正常运行时 ds:[0Eh] 应该是 00 00 吧,所以其实这个 call 应该是转移到 start: 处,并将返回地址及其下一指令地址压栈在 ds:[0Eh] 处;当程序再次有 start: 运行到这个 call 指令时,由于 ds:[0Eh] 处为其后的 inc ax 指令的地址,所以会跳到这个 inc ax 指令接着向下运行,并再次将返回地址压栈到 ds:[0Ch] 处(尽管已经没有意义了);这么运行到最后的程序结束返回 DOS,压栈的两个返回地址也无用武之地。 窃以为,这样的题目设计,有点儿小聪明,但也仅仅是小聪明,并不怎么适合初期的,没有必要在这上面耽搁多少的时间。
CALL的原理应该是先压栈后跳转,所以在跳转的时候DS:[0EH]的值已经被改变了,并不用进行第二次从start重新开始的吧
zara 2013-08-21
  • 打赏
  • 举报
回复
引用
... 并将返回地址及其下一指令地址压栈在 ds:[0Eh] 处 ...
笔误了,应该是
... 并将返回地址其下一指令地址压栈在 ds:[0Eh] 处 ...
zara 2013-08-21
  • 打赏
  • 举报
回复
这个代码不是这么看的,更不能用 debug 来单步什么的,而应该是单纯的静态分析,主要是针对堆栈的作用来的。如果用 debug 单步什么的话,会给堆栈写入内容导致 call 去了错误的地方,失去了这个代码设计的本来意义。
call word ptr ds:[0EH],正常运行时 ds:[0Eh] 应该是 00 00 吧,所以其实这个 call 应该是转移到 start: 处,并将返回地址及其下一指令地址压栈在 ds:[0Eh] 处;当程序再次有 start: 运行到这个 call 指令时,由于 ds:[0Eh] 处为其后的 inc ax 指令的地址,所以会跳到这个 inc ax 指令接着向下运行,并再次将返回地址压栈到 ds:[0Ch] 处(尽管已经没有意义了);这么运行到最后的程序结束返回 DOS,压栈的两个返回地址也无用武之地。

窃以为,这样的题目设计,有点儿小聪明,但也仅仅是小聪明,并不怎么适合初期的,没有必要在这上面耽搁多少的时间。
zara 2013-08-21
  • 打赏
  • 举报
回复
不了解中断吗,还是先看下书上关于中断过程的叙述吧
u010258183 2013-08-21
  • 打赏
  • 举报
回复
引用 4 楼 zara 的回复:
单步,由单步中断实现的;中断,就会有堆栈操作,毕竟最起码要保存的标记寄存器和返回的 CS:IP 都是要使用到用户的当前堆栈的。
毕竟最起码要保存的标记寄存器和返回的 CS:IP 都是要使用到用户的当前堆栈的,看不懂啊,能具体点吗, 标记寄存器是什么意思,返回CS:IP干嘛不明白。这个dos下的debug跟程序通信不是有个psp数据区去存吗,用堆栈干嘛?如果自己没定义栈段,那它存哪里去呢?
zara 2013-08-21
  • 打赏
  • 举报
回复
单步,由单步中断实现的;中断,就会有堆栈操作,毕竟最起码要保存的标记寄存器和返回的 CS:IP 都是要使用到用户的当前堆栈的。
u010258183 2013-08-21
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
这个代码不是这么看的,更不能用 debug 来单步什么的,而应该是单纯的静态分析,主要是针对堆栈的作用来的。如果用 debug 单步什么的话,会给堆栈写入内容导致 call 去了错误的地方,失去了这个代码设计的本来意义。 call word ptr ds:[0EH],正常运行时 ds:[0Eh] 应该是 00 00 吧,所以其实这个 call 应该是转移到 start: 处,并将返回地址及其下一指令地址压栈在 ds:[0Eh] 处;当程序再次有 start: 运行到这个 call 指令时,由于 ds:[0Eh] 处为其后的 inc ax 指令的地址,所以会跳到这个 inc ax 指令接着向下运行,并再次将返回地址压栈到 ds:[0Ch] 处(尽管已经没有意义了);这么运行到最后的程序结束返回 DOS,压栈的两个返回地址也无用武之地。 窃以为,这样的题目设计,有点儿小聪明,但也仅仅是小聪明,并不怎么适合初期的,没有必要在这上面耽搁多少的时间。
这段代码,debug 单步为何会引起堆栈中的数据出现奇怪的数据, dw 8 dup (0)这句代码不是让栈中的数据全部为00吗,但是我查看内存有的地方不是00啊。你说的给堆栈写入内容,是谁写的内容啊,能详细解释下吗?

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧