如何将Linux 32位gcc内联程序集转换为64位代码?
我正在尝试在Linux中使用gcc从32位模式转换为64位模式(长模式)。我熟悉x86 32位汇编(在MS-DOS环境中),但我是x86 64位汇编和Linux汇编编程的初学者 这个项目是供生产使用的(我需要一个工作的非源代码调试器),但我也尝试学习如何进行32位到64位的转换。如果可能的话,我试图找到一种通用的方法来进行32位到64位的转换,这种转换可以在任何使用正则表达式的32位程序上完成(这样就可以实现自动化)。我知道不存在通用的解决方案(64位代码可能比32位代码占用更多的空间,消耗更多的堆栈等),但即使在这种情况下,自动转换的代码也可以作为起点 其思想是保持8位和16位操作数不变,并用64位操作数替换32位操作数。如果如何将Linux 32位gcc内联程序集转换为64位代码?,linux,gcc,assembly,x86-64,inline-assembly,Linux,Gcc,Assembly,X86 64,Inline Assembly,我正在尝试在Linux中使用gcc从32位模式转换为64位模式(长模式)。我熟悉x86 32位汇编(在MS-DOS环境中),但我是x86 64位汇编和Linux汇编编程的初学者 这个项目是供生产使用的(我需要一个工作的非源代码调试器),但我也尝试学习如何进行32位到64位的转换。如果可能的话,我试图找到一种通用的方法来进行32位到64位的转换,这种转换可以在任何使用正则表达式的32位程序上完成(这样就可以实现自动化)。我知道不存在通用的解决方案(64位代码可能比32位代码占用更多的空间,消耗更多
pushw%ax;pushw%bx;popl%ecx
替换为pushw%ax;pushw%bx;popq%rcx
,但性能良好的程序通常不会推送两个16位操作数,然后再推送一个32位操作数,或者这样做
以下是到目前为止的转换:
编辑:修复:pusha
/pushad
可以替换为连续的push
,因为pusha
/pushad
命令在实际推送sp
之前推送esp
的值,而push sp
在286+中的工作方式相同,但在8088/8086中不同。这种差异在这里不是问题(对于386+代码)<因此,可以用连续的push
命令替换code>pusha和pushad
另一种选择与中的类似
编辑:修复:对所有命令使用64位内存寻址
pusha
->push%ax;按%cx;按%dx;按%bx;按%sp;按%bp;推送%si;按%di
编辑:修复:一个有效的替代方案(使用lea
),注意x86处理器是小端:pusha
->movq%rax,-8(%rsp);lea-8(%rsp),%rax;移动百分比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;按%rcx;按%rdx;按%rbx;推送%rsp;按%rbp;推%rsi;按%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
编辑:修复:popa
和popad
弹出sp
/esp
的值,但放弃它()。让我们pop
将其放入bx
/rbx
popa
->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
pushfd
->pushfq
popfd
->popfq
推送段寄存器,例如pushw%ds
->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
inc%reg16
->添加$1,%reg16
,例如inc%ax
->添加$1,%ax
dec%reg16
->sub$1,%reg16
,例如dec%ax
->sub$1,%ax
inc%reg32
->添加$1,%reg64
,例如inc%eax
->添加$1,%rax
dec%reg32
->sub$1,%reg64
,例如dec%eax
->sub$1,%rax
aaa
->aad
->aam
->aas
->arpl
->绑定
->daa
->das
->lahf
->sahf
->pushl$0xDEADBEEF
->pushq%rax;pushq%rax;movq$0xDEADBEEF,%rax;movq%rax,8%(rsp);popq%rax
ret
直接操作数:我认为在这种情况下,必须回溯源代码,以查看最后一个push
ed操作数的大小,并相应地执行操作,例如push%eax;ret 4
->pushq%rax;ret 8
int$0x80
->pushq%rdi;movq%rbp%r9;movq%rdi,%r8;movq%rbx,%rdi;xchgq%rcx,%rsi;——使用替换列表替换%rax值--;系统调用;popq%rdi;xchgq%rcx,%rsi
(注意:32位系统调用可能有6个以上的参数,其中6个在寄存器a中