在GCC中将指针推入eax和ebx寄存器

6

我需要将一个指针推入eax寄存器,另一个指针推入ebx寄存器。我首先用以下方法解决了这个问题:

register int eax asm("eax");
register int ebx asm("ebx");
int main()
{
     eax = ptr1;
     ebx = ptr2;
}

这个方法非常有效。然而,当我将其添加到其他代码中时,我得到了一些奇怪的错误,关于gcc无法在代码中完全不相关的部分找到一个溢出寄存器类AREG。我进行了谷歌搜索,结果发现这实际上是gcc的一个bug。所以,我需要另一种方式来将两个指针推入eax和ebx寄存器中。有人有什么想法吗?

编辑:

由于人们一直在问我在尝试做什么,所以我想解释一下。

我需要更改eax和ebx用于我正在尝试在程序中运行的一些汇编代码。我需要通过eax和ebx寄存器提供指向参数的指针来执行此汇编代码。我通过将指向它的指针推入ebx中并调用ebx来执行汇编代码。当我将注册表内容本地调用而不是全局调用时,汇编代码会崩溃。如果我将其全局调用,则在随机函数结束时会出现奇怪的错误。当我删除该函数时,它会在另一个随机函数中抛出相同的错误。直到我用完所有函数,然后它就可以工作了,但这样我就会错过其余的代码: P


请记住,EAX寄存器用于返回值。同时,它只有32位,因此在64位机器上无法将指针存储在EAX中。 - Some programmer dude
@joachimPileborg 没问题,它是一个32位的exe。你有什么办法可以做到这一点吗? - Noah Goldsmid
3
我查过谷歌,结果显示这实际上是gcc的一个bug。不,它几乎肯定不是。当错误消息在不应该出现时生成时可能会有错误,但这并不意味着每次收到该错误消息时都是编译器bug。有时错误是有效的,而错误消息则提示了代码中的问题所在。 - user743382
你是想将那些寄存器全局分配给两个指针吗?为什么? - Carl Norum
此外,您至少应该指出关于“gcc中的错误”的声明所在的位置。将物理寄存器绑定到已声明的register对象不是C语言的一部分,而是gcc的扩展功能。因此,在没有太多正式规范说明其预期功能的情况下谈论错误有些牵强。 - Jens Gustedt
2个回答

6
如果您有需要在EAX/EBX中指定特定参数的(内联)汇编代码,则在gcc中实现的方法如下:
__asm__("transmogrify %0, %1\n" : "+a"(val_for_eax), "+b"(val_for_ebx));

这里使用了gcc所称的内联汇编约束,告诉编译器汇编代码 - 无论是什么 - 需要在EAX/EBX中期望val_for_eax/val_for_ebx(即a/b部分),并且还会在这些寄存器中返回这些变量的可能修改版本(即+)。除此之外,在asm()语句中的实际代码对于编译器来说并不重要 - 它只需要知道参数%0和%1位于哪里。由于transmogrify指令在当前x86指令集中不存在,因此上述示例在汇编器运行时将失败;只需用有效的指令替换它即可。关于为什么gcc会以这种方式行事以及您可以告诉它做什么的详细说明在GCC手册中有。

你可以为变量指定一个特定的寄存器,但由于gcc的工作方式/inline assembly在gcc中的实现方式,这并不意味着该寄存器从此时起被保留(超出范围)供gcc用于自己的目的。只有通过约束条件才能实现这一点,针对一个特定的、单独的asm()块 - 约束条件告诉gcc在实际汇编代码放置之前应将什么写入这些寄存器,以及在之后从中读取什么。


哎呀,GCC风格的汇编语言真是奇怪,不过,折腾了一会儿之后终于搞定了! - Noah Goldsmid

4

由于在您的架构上,eax寄存器在有效程序中需要使用,因此绑定到特定寄存器的全局变量无法使用您的策略。不要这样做,全局保留寄存器不是一个好主意。

将绑定到寄存器的变量放置在特定函数中,并尽可能靠近它们的使用位置。


我尝试过将它们从全局变量更改为局部变量,但是这样它就无法工作了。 - Noah Goldsmid
你需要更好地解释问题所在,以及你的代码试图实现什么等等。"不起作用"并不是很有建设性。 - Jens Gustedt
我需要更改一些汇编代码中的eax和ebx,以便在我的程序中运行。我需要通过eax和ebx寄存器提供指向参数的指针来执行此汇编代码。我通过将指向它的指针推入ebx并调用ebx来执行汇编代码。 - Noah Goldsmid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接