1

I'm corrently working on changing examples from complex indirect addresssing mode into simple indirect addressing mode pieces. However, I've come across an example from the Based Mode, I'm unable to "transform".

Code:

move %eax, 28(%esp)

I've tried

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

This creates a segmentation fault; and I've no idea how else I should write it.

Another example, I've failed to "transform is

compl $4, 28(%esp)

-> into

addl    $28, %esp
cmpl    $4, %esp

However this is working, but it changes my output slightly, so it might not be correct as well.

4

2 回答 2

1

示例 1:

这个:

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

不做同样的事情move %eax, 28(%esp)。你正在寻找的是这样的:

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

但请注意,您的版本会修改 的值esp,而原始指令不会。


示例 2:

再次,这个:

addl    $28, %esp
cmpl    $4, %esp

不做同样的事情cmpl $4, 28(%esp)。原始指令将地址处内存中的 32 位值esp+28与值 4 进行比较。您的版本将值esp+28与值 4 进行比较(即没有内存访问)。

于 2015-05-13T19:50:58.037 回答
1

免责声明:我不喜欢 AT&T 语法,所以如果以下内容似乎与您想要做的完全相反,我把它搞砸了,您需要切换论点(从的角度来看,相反说明的目的是什么,这与我的意思相反,但似乎做了另一件事……等等,我想我在这里把自己扭曲了)。

(编者注:是的,这是向后的,例如加载而不是存储,并且至少有一个除此之外的向后操作数。现在已修复。)


mov  %eax, 28(%esp)     # store EAX to memory at ESP+28

您需要一个临时寄存器来计算存储地址。如果您正在加载,您可以在目标寄存器中计算,但对于存储,我们需要原始数据地址。这是寻址模式如此方便的原因之一。

mov %esp, %ecx       # copy ESP to ECX
add $28, %ecx        # modify the tmp copy, not the stack pointer
mov %eax, (%ecx)     # store EAX into memory dword pointed to by ECX

正如@nrz 评论的那样,修改 ESP 本身可能会使您的函数稍后在尝试通过使用ret.


类似地,一个小步变体

cmpl  $4, 28(%esp)

mov   %esp, %eax
add   $28, %eax
cmpl  $4, (%eax)     # compare immediate with dword pointed to by EAX

或者,如果最后一行太复杂(因为也是间接的),

mov (%eax), %eax
cmp $4, %eax         # dword operand size (cmpl) implied by the register

请注意,此指令序列会改变%eax,而原始单条指令则不会。这是有原因的:提供间接指针操作是因为它们不需要中间寄存器。(而且因为它们节省了指令,增加了每条指令和每字节代码可以完成的工作量。)

在 Z80 等较旧的 CPU 中,确实必须通过“手动”加载一个寄存器作为基址,添加偏移量,然后加载目标值来进行间接寻址。

于 2015-05-13T20:14:20.990 回答