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

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

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

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

到目前为止,这些转换是:

编辑:修正: pusha / pushad 可以用连续push来replace,因为pusha / pushad命令在sp的实际推送之前推送sp / esp的值,而push sp在286+中以相同的方式工作,但在8088 / 8086 汇编语言数据库 。 这个区别不是这里的问题(对于386+代码)。 pushapushad可以被连续的push命令replace。

另一种方法与OpenSolaris的privregs.h代码类似。

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

  1. pusha – > push %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di push %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di push %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di

    编辑:修复:一个有效的替代(使用lea ),请注意,x86处理器是little-endian: pusha – > 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 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 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

  2. pushad – > push %rax; push %rcx; push %rdx; push %rbx; push %rsp; push %rbp; push %rsi; push %rdi push %rax; push %rcx; push %rdx; push %rbx; push %rsp; push %rbp; push %rsi; push %rdi 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), %rsp 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), %rsp 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), %rsp

    编辑:修正: popapopadpopupsp / esp的值,但放弃它( 英特尔指令集 – popa / popad )。 让我们把它popbx / rbx

  3. popa – > popw %di; popw %si; popw %bp; popw %bx; popw %bx; popw %dx; popw %cx; popw %ax popw %di; popw %si; popw %bp; popw %bx; popw %bx; popw %dx; popw %cx; popw %ax popw %di; popw %si; popw %bp; popw %bx; popw %bx; popw %dx; popw %cx; popw %ax

  4. popad – > popq %rdi; popq %rsi; popq %rbp; popq %rbx; popq %rbx; popq %rdx; popq %rcx; popq %rax popq %rdi; popq %rsi; popq %rbp; popq %rbx; popq %rbx; popq %rdx; popq %rcx; popq %rax popq %rdi; popq %rsi; popq %rbp; popq %rbx; popq %rbx; popq %rdx; popq %rcx; popq %rax

  5. pushfd – > pushfq

  6. popfd – > popfq

  7. 编辑: push段的寄存器,例如。 pushw %ds – > pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax

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

  9. 编辑: inc %reg16 – > add $1, %reg16 ,例如。 inc %ax – > add $1, %ax

  10. 编辑: dec %reg16 – > sub $1, %reg16 ,例如。 dec %ax – > sub $1, %ax

  11. 编辑: inc %reg32 – > add $1, %reg64 ,例如。 inc %eax – > add $1, %rax

  12. 编辑: dec %reg32 – > sub $1, %reg64 ,例如。 dec %eax – > sub $1, %rax

  13. 编辑: aaa – >?

  14. 编辑: aad – >?

  15. 编辑: aam – >?

  16. 编辑: aas – >?

  17. 编辑: arpl – >?

  18. 编辑: bound – >?

  19. 编辑: daa – >?

  20. 编辑: das – >?

  21. 编辑: lahf – >?

  22. 编辑: sahf – >?

  23. 编辑修正:在64位模式下,直接操作数不适合32位操作数大小的任何命令,例如。 pushl $0xDEADBEEF – > pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax

  24. ret的立即操作数:我认为在这种情况下,源代码必须回溯到最后pushed操作数的大小,并采取相应的行动,例如。 pushl %eax; ret 4 pushl %eax; ret 4 – > pushq %rax; ret 8 pushq %rax; ret 8

  25. 编辑::系统调用: int $0x80 – > pushq %rdi; movq %rbp, %r9; movq %rdi, %r8; movq %rbx, %rdi; xchgq %rcx, %rsi; -- replace %rax value using a substitution list --; syscall; popq %rdi; xchgq %rcx, %rsi pushq %rdi; movq %rbp, %r9; movq %rdi, %r8; movq %rbx, %rdi; xchgq %rcx, %rsi; -- replace %rax value using a substitution list --; syscall; popq %rdi; xchgq %rcx, %rsi pushq %rdi; movq %rbp, %r9; movq %rdi, %r8; movq %rbx, %rdi; xchgq %rcx, %rsi; -- replace %rax value using a substitution list --; syscall; popq %rdi; xchgq %rcx, %rsi (注意:32位系统调用可能有6个以上的参数,其中6个是寄存器,其余的是堆栈,64位系统调用可能永远不会超过6个参数)。

编辑:还应该考虑到什么? 将32位代码转换为64位代码需要进行哪些转换(以长模式运行)?

Solutions Collecting From Web of "如何将Linux 32位gcc内联汇编转换为64位代码?"