如何将Linux 32位gcc内联汇编转换为64位代码?

时间:2012-08-10 07:20:36

标签: linux gcc assembly x86-64 inline-assembly

我正在尝试使用gcc在Linux中将RR0D Rasta Ring 0 Debugger从32位模式转换为64位模式(长模式)。我熟悉x86 32位程序集(在MS-DOS环境中),但我是x86 64位程序集和Linux程序集编程的初学者。

这个项目是供生产使用的(我需要一个可用的非源调试器),但我也尝试学习如何进行32位到64位的转换。如果可能的话,我试图找到一种通用的方法来进行32位到64位的转换,可以使用正则表达式在任何32位程序上完成(这样它就可以自动化)。我知道没有通用的解决方案(64位代码可能占用比32位代码更多的空间等,并消耗更多的堆栈等),但即使在这种情况下,自动转换的代码也可作为起点。

这个想法是按原样保留8位和16位操作数,并用64位操作数替换32位操作数。如果用pushw %ax; pushw %bx; popl %ecx替换pushw %ax; pushw %bx; popq %rcx,这种方法自然会失败,但是行为良好的程序通常不会push两个16位操作数,然后pop一个32位操作数,还是他们?。

这些是到目前为止的转化次数:

修改修复:pusha / pushad 可以替换为连续的push,因为{{1} } / pusha命令在实际推送pushad之前推送sp / esp 的值,而sp的工作方式相同在286 +中的方式,但在8088/8086 The Assembly Language database中有所不同。这种差异不是问题(对于386+代码)。因此push sppusha可以用连续的pushad命令替换。

替代方案与OpenSolaris' privregs.h code类似。

编辑:修复:对所有命令使用64位内存寻址。

  1. push - > pusha

    修改修复:有效的替代方案(使用push %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di),请注意x86处理器是little-endian:lea - > pusha

  2. movq %rax, -8(%rsp); lea -8(%rsp), %rax; mov %ax, -10(%rsp); movq -8(%rsp), %rax; movw %cx, -4(%rsp); movw %dx, -6(%rsp); movw %bx, -8(%rsp); movw %bp, -12(%rsp); movw %si, -14(%rsp); movw %di, -16(%rsp); lea -16(%rsp), %rsp - > pushad

    修改:修正:有效替代方案(使用push %rax; push %rcx; push %rdx; push %rbx; push %rsp; push %rbp; push %rsi; push %rdi):lea - > pushad

    修改:修正:movq %rax, -8(%rsp); movq %rcx, -16(%rsp); movq %rdx, -24(%rsp); movq %rbx, -32(%rsp); lea -32(%rsp), %rax; movq %rax, -40(%rsp); movq -8(%rsp), %rax; movq %rbp, -48(%rsp); movq %rsi, -56(%rsp); movq %rdi, -64(%rsp); lea -64(%rsp), %rsppopa弹出popad / sp的值但丢弃它(Intel instruction set - popa/popad) 。我们将esp改为pop / bx

  3. rbx - > popa

  4. popw %di; popw %si; popw %bp; popw %bx; popw %bx; popw %dx; popw %cx; popw %ax - > popad

  5. popq %rdi; popq %rsi; popq %rbp; popq %rbx; popq %rbx; popq %rdx; popq %rcx; popq %rax - > pushfd

  6. pushfq - > popfd

  7. 编辑: popfq段寄存器,例如。 push - > pushw %ds

  8. 编辑: pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax段寄存器,例如。 pop - > popw %ds

  9. 修改: pushw %ax; movw 2(%rsp), %ax; movw %ax, %ds; popw %ax - > inc %reg16,例如。 add $1, %reg16 - > inc %ax

  10. 修改: add $1, %ax - > dec %reg16,例如。 sub $1, %reg16 - > dec %ax

  11. 修改: sub $1, %ax - > inc %reg32,例如。 add $1, %reg64 - > inc %eax

  12. 修改: add $1, %rax - > dec %reg32,例如。 sub $1, %reg64 - > dec %eax

  13. 修改: sub $1, %rax - >

  14. 修改: aaa - >

  15. 修改: aad - >

  16. 修改: aam - >

  17. 修改: aas - >

  18. 修改: arpl - >

  19. 修改: bound - >

  20. 修改: daa - >

  21. 修改: das - >

  22. 修改: lahf - >

  23. 编辑修复:任何具有直接操作数的命令,在64位模式下不适合32位操作数大小,例如。 sahf - > pushl $0xDEADBEEF

  24. 带有立即操作数的
  25. pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax:我认为在这种情况下,必须回溯源代码以查看最后ret个ed操作数的大小,并相应地采取行动,例如。 push - > pushl %eax; ret 4

  26. 修改:系统调用:pushq %rax; ret 8 - > int $0x80(注意:32位系统调用可能有6个以上的参数,6个在寄存器中,其余的在堆栈中,64位系统调用可能永远不会超过6个参数)。

  27. 修改:还应该考虑哪些因素?将32位代码转换为64位代码(以长模式运行)需要进行哪些其他转换?

0 个答案:

没有答案