GCC内联汇编来操纵所有寄存器?

时间:2013-11-05 22:10:23

标签: c gcc assembly x86 inline-assembly

我正在尝试在C(GCC 4.6.3,x86(64位CPU),Ubuntu 12.04 64位)中进行一些汇编调用,以将寄存器值清零并设置堆栈指针,并最终调用跳转指令

这就是我得到的:

asm("xor %eax, %eax");
asm("xor %ebx, %ebx");
asm("xor %ecx, %ecx");
asm("xor %edx, %edx");

asm("xor %cs, %cs");
asm("xor %ds, %ds");
asm("xor %es, %es");
asm("xor %fs, %fs");
asm("xor %gs, %gs");
asm("xor %ss, %ss");

asm("xor %esi, %esi");
asm("xor %edi, %edi");
asm("xor %ebp, %ebp");
asm("xor %esp, %esp");

asm("xor %cr0, %cr0");
asm("xor %cr1, %cr1");
asm("xor %cr2, %cr2");
asm("xor %cr3, %cr3");
asm("xor %cr4, %cr4");

asm("xor %cr8, %cr8");

当我尝试编译时,除了前四个寄存器之外的所有寄存器都说Error: operand type mismatch for 'xor'。基本上,我需要将所有寄存器内容清零(不知道该怎么做)。显然有一个rdx重要的注册表?但我在网上看了看,找不到清单。

接下来,我需要将堆栈指针设置为特定的内存位置。我怎么能这样做?

最后,我需要调用jump指令并转到特定的内存位置。我怎么能这样做?

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

你无法直接操作cs,ds,es,fs,gs,ss寄存器的值,将它们归零,从eax,ebx,ecx,edx,esi,edi,esp等寄存器中移出零值:

asm("xor %eax, %eax");
asm("mov %ds, %eax");

如果您使用E前缀将二进制文件编译为64位,则只能访问寄存器的低32位。上半部分不会归零。要编码64位汇编,请使用R前缀,例如rax。然后,如果您试图将自己的C风格函数纯粹与它自己的调用堆栈进行汇编并使用32位寄存器并以64位模式运行它,它就会崩溃。

您应该学会使用推送和弹出指令,并且应该在任何内联汇编之前备份您在C代码中更改的所有寄存器,然后再恢复它们。如果你的装配不会弄乱你的C代码,它会或多或少地随机崩溃。例如:

// pack them up
asm("push %eax");
asm("push %ds");
// do something
asm("xor %eax, %eax");
asm("mov %ds, %eax");
// restore them back in opposite order (it's a stack)
asm("pop %ds");
asm("pop %eax");

See here

接下来,您甚至无法将值移动到CS:IP寄存器中,但您可以使用jump,call和ret系列指令间接修改它们的值,但是您不能在代码中执行此操作,因为您的代码将会跳转(随机)(如果你将地址清零,则为零)地址,它会崩溃。

有关CS:IP的更多信息,请参阅此链接: Change CS:IP in Assembly Language

答案 1 :(得分:2)

主要问题是xor无法对段或控制寄存器进行操作。另请注意,归零控制寄存器只能在内核模式下完成,零可能对它们没有意义。

此外,gcc inline asm有自己独特的语法,将这段代码写在一个单独的asm文件中可能最容易。

您应该阅读intel手册和gcc手册。