Как конвертировать 32-разрядную сборку Linux в gcc в 64-битный код?

Я пытаюсь преобразовать RR0D Rasta Ring 0 Debugger из 32-разрядного режима в 64-разрядный (длинный) режим в Linux, используя gcc. Я знаком с 32-разрядной сборкой x86 (в среде MS-DOS), но я новичок в 64-разрядной сборке x86 и в Linux-сборке в целом.

Этот проект предназначен для использования в производственных целях (мне нужен рабочий отладчик, не являющийся источником), но я также пытаюсь узнать, как сделать преобразование с 32-разрядным и 64-разрядным. Если возможно, я пытаюсь найти универсальный способ выполнить преобразование 32-битного в 64-битное, которое может быть выполнено на любой 32-разрядной программе с использованием регулярных выражений (чтобы можно было автоматизировать). Я знаю, что не существует общего решения (64-разрядный код может занимать больше места, чем 32-разрядный код и т.д., И потреблять больше стека и т.д.), Но даже в этом случае автоматически преобразованный код будет служить отправной точкой.

Идея состояла в том, чтобы сохранить 8-битные и 16-разрядные операнды как есть, и заменить 32-разрядные операнды на 64-битные операнды. Этот подход, естественно, потерпит неудачу, если pushw %ax; pushw %bx; popl %ecx будет заменено на pushw %ax; pushw %bx; popq %rcx, но в хорошо управляемых программах обычно не push два 16-битных операнда, а затем pop один 32-разрядный операнд или они?.

Это до сих пор конверсии:

Изменить: Исправление: pusha/pushad может быть заменено последовательными push 'es, потому что команды pusha/pushad значение sp/esp до фактического нажатия sp, а push sp работает одинаково в 286+, но по-разному в 8088/8086 База данных языка Ассамблеи. Эта разница не проблема здесь (для 386 + кода). pusha и pushad могут быть заменены последовательными командами push.

Альтернатива аналогична альтернативе код OpenSolaris privregs.h.

Изменить: Исправление: используйте 64-битную адресацию памяти для всех команд.

  • pushapush %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di.

    Изменить: Исправление: действительная альтернатива (с использованием lea), обратите внимание, что x86-процессоры малозначительны: pushamovq %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.

  • pushadpush %rax; push %rcx; push %rdx; push %rbx; push %rsp; push %rbp; push %rsi; push %rdi.

    Изменить: Исправить: действительная альтернатива (с помощью lea): pushadmovq %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, но отбросьте его (Набор инструкций Intel - popa/popad). Пусть pop it в bx/rbx.

  • popapopw %di; popw %si; popw %bp; popw %bx; popw %bx; popw %dx; popw %cx; popw %ax.

  • popadpopq %rdi; popq %rsi; popq %rbp; popq %rbx; popq %rbx; popq %rdx; popq %rcx; popq %rax.

  • pushfdpushfq.

  • popfdpopfq.

  • Изменить: push сегментных регистров, например. pushw %dspushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax.

  • Изменить: pop сегментных регистров, например. popw %dspushw %ax; movw 2(%rsp), %ax; movw %ax, %ds; popw %ax.

  • Изменить: inc %reg16add $1, %reg16, например. inc %axadd $1, %ax.

  • Изменить: dec %reg16sub $1, %reg16, например. dec %axsub $1, %ax.

  • Изменить: inc %reg32add $1, %reg64, например. inc %eaxadd $1, %rax.

  • Изменить: dec %reg32sub $1, %reg64, например. dec %eaxsub $1, %rax.

  • Изменить: aaa → ?

  • Изменить: aad → ?

  • Изменить: aam → ?

  • Изменить: aas → ?

  • Изменить: arpl → ?

  • Изменить: bound → ?

  • Изменить: daa → ?

  • Изменить: das → ?

  • Изменить: lahf → ?

  • Изменить: sahf → ?

  • Изменить Исправление: любая команда с прямым операндом, которая не соответствует размеру 32-разрядного операнда в 64-битном режиме, например. pushl $0xDEADBEEFpushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax.

  • ret с непосредственным операндом: я думаю, в этом случае исходный код должен быть возвращен, чтобы увидеть размеры последних push ed операндов и действовать соответственно, например. pushl %eax; ret 4pushq %rax; ret 8.

  • Изменить:: syscalls: int $0x80pushq %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 -bit syscalls никогда не может иметь более 6 параметров).

Изменить: Что еще нужно учитывать? Какие еще преобразования понадобится для преобразования 32-битного кода в 64-разрядный код (для запуска в длинном режиме)?