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

Я пытаюсь конвертироватьRR0D Rasta Ring 0 Отладчик из 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-битный операнд, или они?

Это преобразования пока:

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

Альтернатива похожа наOpenSolaris & APOS;privregs.h code.

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

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

Edit: Fix: A valid alternative (using lea), note that x86 processors are 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.

pushad -> push %rax; push %rcx; push %rdx; push %rbx; push %rsp; push %rbp; push %rsi; push %rdi.

Edit: Fix: A valid alternative (using 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.

Edit: Fix: popa and popad pop the value of sp / esp but discard it (Intel instruction set - popa/popad) . Let's pop it into 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.

Edit: push of segment registers, eg. pushw %ds -> pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax.

Edit: pop of segment registers, eg. popw %ds -> pushw %ax; movw 2(%rsp), %ax; movw %ax, %ds; popw %ax.

Edit: inc %reg16 -> add $1, %reg16, eg. inc %ax -> add $1, %ax.

Edit: dec %reg16 -> sub $1, %reg16, eg. dec %ax -> sub $1, %ax.

Edit: inc %reg32 -> add $1, %reg64, eg. inc %eax -> add $1, %rax.

Edit: dec %reg32 -> sub $1, %reg64, eg. dec %eax -> sub $1, %rax.

Edit: aaa -> ?

Edit: aad -> ?

Edit: aam -> ?

Edit: aas -> ?

Edit: arpl -> ?

Edit: bound -> ?

Edit: daa -> ?

Edit: das -> ?

Edit: lahf -> ?

Edit: sahf -> ?

Edit Fix: any command with direct operand that does not fit in 32-bit operand size in 64-bit mode, eg. pushl $0xDEADBEEF -> pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax.

ret with immediate operand: I think in this case the source code must be backtraced to see the sizes of last pushed operands, and act accordingly, eg. pushl %eax; ret 4 -> pushq %rax; ret 8.

Edit:: syscalls: 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 (note: 32-bit syscalls may have more than 6 parameters, 6 in registers and the rest in stack, 64-bit syscalls may never have more than 6 parameters).

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

Ответы на вопрос(0)

Ваш ответ на вопрос