我试图在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 %ecx
被pushw %ax; pushw %bx; popq %rcx
replacepushw %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+代码)。 pusha
和pushad
可以被连续的push
命令replace。
另一种方法与OpenSolaris的privregs.h
代码类似。
编辑:修复:使用64位内存寻址所有命令。
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
。
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
。
编辑:修正: popa
和popad
popupsp
/ esp
的值,但放弃它( 英特尔指令集 – popa / popad )。 让我们把它pop
入bx
/ rbx
。
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
。
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
。
pushfd
– > pushfq
。
popfd
– > popfq
。
编辑: 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
。
编辑:段寄存器的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
。
编辑: inc %reg16
– > add $1, %reg16
,例如。 inc %ax
– > add $1, %ax
。
编辑: dec %reg16
– > sub $1, %reg16
,例如。 dec %ax
– > sub $1, %ax
。
编辑: inc %reg32
– > add $1, %reg64
,例如。 inc %eax
– > add $1, %rax
。
编辑: dec %reg32
– > sub $1, %reg64
,例如。 dec %eax
– > sub $1, %rax
。
编辑: aaa
– >?
编辑: aad
– >?
编辑: aam
– >?
编辑: aas
– >?
编辑: arpl
– >?
编辑: bound
– >?
编辑: daa
– >?
编辑: das
– >?
编辑: lahf
– >?
编辑: sahf
– >?
编辑修正:在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
。
ret
的立即操作数:我认为在这种情况下,源代码必须回溯到最后pushed操作数的大小,并采取相应的行动,例如。 pushl %eax; ret 4
pushl %eax; ret 4
– > pushq %rax; ret 8
pushq %rax; ret 8
。
编辑::系统调用: 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位代码需要进行哪些转换(以长模式运行)?