Я пытаюсь преобразовать 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-битную адресацию памяти для всех команд.
-
pusha
→push %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di
.Изменить: Исправление: действительная альтернатива (с использованием
lea
), обратите внимание, что x86-процессоры малозначительны: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
.Изменить: Исправить: действительная альтернатива (с помощью
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
, но отбросьте его (Набор инструкций Intel - popa/popad). Пустьpop
it в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
. -
Изменить:
push
сегментных регистров, например.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
→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
→ ? -
Изменить Исправление: любая команда с прямым операндом, которая не соответствует размеру 32-разрядного операнда в 64-битном режиме, например.
pushl $0xDEADBEEF
→pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax
. -
ret
с непосредственным операндом: я думаю, в этом случае исходный код должен быть возвращен, чтобы увидеть размеры последнихpush
ed операндов и действовать соответственно, например.pushl %eax; ret 4
→pushq %rax; ret 8
. -
Изменить:: 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
(примечание: 32-разрядные системные вызовы могут содержать более 6 параметров, 6 в регистре и остальные в стеке, 64 -bit syscalls никогда не может иметь более 6 параметров).
Изменить: Что еще нужно учитывать? Какие еще преобразования понадобится для преобразования 32-битного кода в 64-разрядный код (для запуска в длинном режиме)?