64位问题:尝试使用内联汇编将%rsp中的值复制到临时变量中

时间:2010-06-24 03:42:50

标签: c x86-64 inline-assembly

我正在使用一个操作系统设计类,在这个类中,他们给了我们一个用C编写的微内核,我们正在构建它。内核似乎是考虑到32位机器设计的,我正在运行雪豹。所以我和班上的朋友一直试图将其破解成64位寻址。

最大的问题似乎是一行代码,其中使用内联汇编将当前堆栈指针复制到调度程序使用的临时变量中:

#define SET_STACK(s) asm("movl temp,%esp");

当然,编译器会向我发回错误,因为%esp是32位寄存器。

/var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cckS2oq7.s:523:32-bit absolute addressing is not supported for x86-64
/var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cckS2oq7.s:523:cannot do signed 4 byte relocation

所以我用%rsp替换它,因为它是64位堆栈指针寄存器(我认为只有%sp也可以工作,我在这里读到的其他地方GAS足够智能放置正确的前缀)。将%esp替换为%rsp后,我收到此错误:

/var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cc8TLdjH.s:523:Incorrect register `%sp' used with `l' suffix

现在,我有点不知所措,因为我对汇编程序并不熟悉。我尝试用movlmov替换movq,但似乎没有任何效果。这让我相信temp可能是错误的大小?

Temp是一个全局变量,声明如下:

void* temp;   // temp pointer used in dispatcher

我写了一个快速程序来打印出不同数据类型的大小,看起来像x86-64中的void *是8个字节大小,应该是正确的大小,对吗?

无论如何,显然我不希望有人为我解决这个问题,但任何可能指向正确方向的提示都会非常感激!

2 个答案:

答案 0 :(得分:2)

您显示的行不会将%esp中的值复制到temp - 它会反过来(如SET_STACK所暗示的那样)。 AT& T语法为src, dest

一个简单的asm("mov temp, %rsp");应该编译。

答案 1 :(得分:1)

你需要使用movq进行64位移动。

这是一个装配片段从我的一个项目(火车模拟器的一部分)做一些SSE工作,评论的行是32位英特尔asm,未注释的是64位AT& T.

asm(
        //mykda calculation
        //mov eax, dword ptr [train_traction_ptr]
        //movaps xmm0, xmmword ptr [eax] //train_traction[i] + forceFront
        "movq %0, %%rax\n\t"
        "movaps (%%rax), %%xmm0\n\t"

        //mov eax, dword ptr [local_fgrr_ptr]
        //movaps xmm1, xmmword ptr [rax]
        //addps xmm0, xmm1
        "movq %1, %%rax\n\t"
        "movaps (%%rax), %%xmm1\n\t"
        "addps %%xmm1, %%xmm0\n\t"

        ... );

评论后我进一步观察,发现所有64位OSX代码都必须独立于位置。

没有Mac测试,但

asm ("movq temp(%rip),%rsp");

应该有效。如果没有,则需要为汇编程序使用适当的PIC寻址。