x86 mov / add指令和内存寻址

x86 mov / add Instructions & Memory Addressing

我正在学习 class 中的 x86 汇编,我对如何区分寄存器操作数和内存引用的作用感到非常困惑。我有几个困惑,希望能澄清。

下面的代码是我教科书上说的分别做push和pop的long way:

subl , %esp
movl %ebp, (%esp)

movl (%esp), %eax
addl , %esp

那么在 subl 指令中,我们总能期望 %esp 保存一个地址值吗?

还有这两个movl函数有什么区别?第一个可以写成

movl (%ebp), %esp

?对于第二个 movl,是移动 %esp 的地址还是移动 %esp 指向的值?

作为后续行动,为什么我们不能像这样让源和目标成为内存引用?

movw (%eax), 4(%esp)

最后,对于以下代码:

movb (%esp, %edx, 4), %dh

如果源超过 1 个字节(%dh 的大小),那么会发生什么?它只是截断值吗?

抱歉,问题太多了,我们将不胜感激。

The following code is what my textbook says is the long way to do push and pop respectively:

subl , %esp
movl %ebp, (%esp)

movl (%esp), %eax
addl , %esp

So in the subl instruction, can we always expect %esp to hold an address value?

是的。 ESP 寄存器保存最后一个压入堆栈的值的内存地址。

Also what is the difference between the two movl functions? Can the first one be written as

movl (%ebp), %esp

? And for the second movl, does that move the address of %esp or does it move the value pointed to by %esp?

MOV 指令在 AT&T 语法中需要两个操作数:源和目标。 MOV 将数据(在本例中为 32 位,由 L 后缀表示)从写入左侧的第一个操作数复制到写入右侧的第二个操作数。如果其中一个被括号括起来,则表示该操作数是一个内存操作数,括号中的值是它的内存地址,而不是实际值)

所以,movl %ebp,(%esp)的意思是:将寄存器EBP的值复制到内存中,在寄存器ESP.

的值指向的地址

movl (%ebp),%esp的意思是:从EBP的值指向的内存地址开始复制32位数据到ESP寄存器中。

所以你正在改变运动的方向。

As a follow-up then, why can't we have the source and destination be memory references like so?

movw (%eax), 4(%esp)

简短回答:因为英特尔使用的编码不允许这样做。长答案:英特尔设计 ISA 的方式,可用资源计算老式 8086 中的两个有效地址等

And lastly, for the following code:

movb (%esp, %edx, 4), %dh

if the source is more than 1 byte (the size of %dh), then what happens? Does it just truncate the value?

源与目标大小相同。这是由 B 后缀和目标是 8 位寄存器这一事实强加的。括号中的值就是单个内存字节的地址。对了,这个地址是ESP+EDX*4

So in the subl instruction, can we always expect %esp to hold an address value?

根据定义是的,因为下一条指令使用它作为地址。无论里面有什么垃圾,现在都有一个地址。如果它是像 0xDEADBEEF 这样的废话..那么现在就是一个地址。它可能是也可能不是有效地址(希望是有效的,无效的堆栈是一件坏事),但这是另一回事。

Also what is the difference between the two movl functions?

"push"中使用的写入内存,"pop"中使用的读取。右侧的括号表示它是写入,左侧的括号表示它是读取。那么你能把它们调过来吗?显然不是,它会做一些不同的事情。 movl (%ebp), %esp 将从内存中读取一些内容,然后更改堆栈所在的位置。

As a follow-up then, why can't we have the source and destination be memory references like so?

因为不能,所以没有这样的说明。它不适合正常的 operand encoding。我想这样的指令可能已经存在,但它不存在,所以你不能使用它。

movb (%esp, %edx, 4), %dh if the source is more than 1 byte (the size of %dh), then what happens?

根据定义,指令不会读取 1 个字节。