如何将Linux 32位gcc内联程序集转换为64位代码?

如何将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位代码占用更多的空间,消耗更多

我正在尝试在Linux中使用gcc从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
,但性能良好的程序通常不会推送两个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
    ->

  • 编辑修复:在64位模式下,任何直接操作数不适合32位操作数大小的命令,例如
    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中