使用程序集代码调用地址



在我们的应用程序中,我有以下源代码:

#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位进行重建。

最新更新