我正在上一门操作系统设计课,他们给了我们一个用 C 编写的微内核,我们正在构建它。内核似乎是为 32 位机器设计的,我正在运行雪豹。因此,我和类的一个 friend 一直在尝试将其破解为 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 个字节,这应该是正确的大小,对吧?

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

最佳答案

您需要使用 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 寻址临时地址。

关于c - 64 位问题 : trying to copy value from %rsp into temp variable using inline assembly,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3107088/

10-10 21:28
查看更多