在我们的应用程序中,我有以下源代码:
#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
指令
asm("movl 4(%%ebp),%0;" : "=r"(VAR));
将32位数量从CCD_ 2复制到CCD_。在您的案例中,VAR
被定义为calladdr
。这假设返回地址是32位的,这在64位系统中不再是真的,并且它假设返回地址在[EBP+4]
,这在64bit系统中也不再是真。
它失败的原因是calladdr
有点像[EBP-x]
(其中x是4之类的数字),并且没有一条Intel x86指令既能从[EBP+4]
中提取又能存储在[EBP-x]
中,所以从[EBP+4]
中提取的值必须存储在某个寄存器中,然后该寄存器的值必须存储在[EBP-x]
中。然后,由于一些我不知道的原因,gcc决定使用寄存器rax
执行此任务,但rax
是64位宽的,而movl
指令的前缀"l"意味着32位数量,因此存在不匹配。
即使你设法解决了这个问题,你的下一个问题是在64位体系结构上,返回地址不在[EBP+4]
。
所以,整个子句是假设你是32位的。
我的建议是:彻底抛弃这种无稽之谈,用一些现成的库(无需重新发明轮子)来代替它,它可以在32位和64位模式下工作,或者像Michael Petch建议的那样,用gcc的内置函数来检索返回地址;然后像老板一样在64位进行重建。