在我们的应用程序中,我有以下源代码:
#define GET_CALL_ADDRESS(VAR) asm("movl 4(%%ebp),%0;" : "=r"(VAR));
void * _our_malloc(size_t size)
{
unsigned long calladdr;
...
GET_CALL_ADDRESS(calladdr);
...
return p;
}
我想知道GET_CALL_ADDRESS
做了什么?此代码在32位计算机上编译并正常工作。
但是在64位机器上,在编译期间我收到以下错误:
Error: incorrect register `%rax' used with `l' suffix
答案 0 :(得分:1)
指令
asm("movl 4(%%ebp),%0;" : "=r"(VAR));
将32位数量从[EBP+4]
复制到VAR
。您的案例中的VAR
定义为calladdr
。这假设返回地址是32位,这在64位系统中不再是真的,它假定返回地址为[EBP+4]
,这在64位系统中也不再正确。
它失败的原因是calladdr
类似于[EBP-x]
(其中x是某个数字,如4),并且没有单一的Intel x86指令可以从{{1}获取并存储在[EBP+4]
,因此从[EBP-x]
获取的值必须存储在某个寄存器中,然后该寄存器的值必须存储在[EBP+4]
。然后对于一些我不知道的原因gcc决定使用寄存器[EBP-x]
来完成这项工作,但是rax
是64位宽,而rax
指令的'l'前缀意味着32比特数量,所以存在不匹配。
即使您以某种方式设法解决了这个问题,您的下一个问题是在64位架构上,返回地址不在movl
。
因此,整个子句假设你是32位。
我的建议:彻底抛弃这个废话并将其替换为一些现成的库(无需重新发明轮子),它可以在32位和64位模式下工作,或者使用gcc的内置函数检索返回地址,如Michael Petch建议的那样;然后像老板那样继续重建64位。