我正在学习类中的x86程序集,我很遗憾你如何区分寄存器操作数和内存引用的作用 . 我有几个想要澄清的混乱 .
以下代码是我的教科书所说的分别是推送和弹出的漫长道路:
subl $4, %esp
movl %ebp, (%esp)
movl (%esp), %eax
addl $4, %esp
那么在subl指令中,我们是否总能指望%esp保存地址值?
两个movl函数之间有什么区别?可以将第一个写成
movl (%ebp), %esp
?对于第二个movl,是移动%esp的地址还是移动%esp指向的值?
作为后续行动,我们为什么不能将源和目标作为内存引用呢?
movw (%eax), 4(%esp)
最后,对于以下代码:
movb (%esp, %edx, 4), %dh
如果源是超过1个字节(%dh的大小),那么会发生什么?它只是截断了这个值吗?
对不起,这是一大堆问题,但任何帮助将不胜感激 .
2 回答
movl(%esp),%eax
addl $ 4,%esp
那么在subl指令中,我们是否总能指望%esp保存地址值?
是 .
ESP
寄存器保存推入堆栈的最后一个值的内存地址 .MOV
语句中的MOV
指令需要两个操作数:源和目标 .MOV
将数据(在本例中为32位,由L
后缀表示)从左侧写入的第一个操作数复制到右侧写入的第二个操作数 . 如果其中一个括在括号中,则表示操作数是内存操作数,括号中的值是其内存地址,而不是实际值)因此,
movl %ebp,(%esp)
表示:将寄存器EBP
的值复制到内存中,寄存器寄存器ESP
的值指向的地址 .你对
movl (%ebp),%esp
的意思是:将从EBP
的值指向的存储器地址开始的32位数据复制到ESP
寄存器中 .所以你正在改变运动的方向 .
简短回答:因为英特尔使用的编码不允许这样做 . 答案很长:英特尔设计ISA的方式,可用资源来计算好旧8086中的两个有效地址等
源与目标的大小相同 . 这是由
B
后缀和目标是8位寄存器的事实强加的 . 括号中的值则是单个存储器字节的地址 . 顺便说一下,这个地址是ESP+EDX*4
根据定义是,因为下一条指令将其用作地址 . 无论垃圾是什么,现在都有一个地址 . 如果它是像0xDEADBEEF那样的废话..那么现在是一个地址 . 它可能是也可能不是有效地址(希望有效,无效堆栈是一件坏事),但这是另一回事 .
"push"中使用的那个写入内存,"pop"中使用的那个读取 . 右侧的括号表示它是一个读数 . 所以你可以切换它们吗?显然不是,它会做一些不同的事情 .
movl (%ebp), %esp
将从内存中读取内容然后更改堆栈的位置 .因为你可以't, there is no such instruction. It wouldn' t适合正常的operand encoding . 我想这样的指令可能已存在,但它并没有使用它 .
根据定义,指令不会读取1个字节 .