我正在努力将复杂的间接寻址模式中的示例更改为简单的间接寻址模式。 但是,我在基础模式中遇到了一个例子,我无法转换"。
代码:
move %eax, 28(%esp)
我已经尝试了
addl $28, %esp
movl (%eax), %esp
这会产生分段错误;而且我不知道我该怎么写它。
另一个例子,我未能"转换是
compl $4, 28(%esp)
- >成
addl $28, %esp
cmpl $4, %esp
然而这是有效的,但它稍微改变了我的输出,所以它可能也不正确。
答案 0 :(得分: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)
做同样的事情。原始指令将地址esp+28
的内存中的32位值与值4进行比较。您的版本将值esp+28
与值4进行比较(即没有内存访问)。< / p>
答案 1 :(得分:1)
免责声明:我不喜欢AT&amp; 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
,而原始单指令则不会。有一个原因:提供间接指针操作因为它们不需要中间寄存器。 (并且因为它们保存了指令,增加了每条指令和每字节代码可以完成的工作量。)
在较旧的CPU(例如Z80)中,确实 通过“手动”加载寄存器作为基础来进行间接寻址,添加偏移量,然后加载目标值。