Jak przekonwertować 32-bitowy zestaw inline gcc Linuksa na kod 64-bitowy? [Zamknięte]

Próbuję się przekonwertowaćDebuger RR0D Rasta Ring 0 z trybu 32-bitowego do trybu 64-bitowego (tryb długi) w systemie Linux, przy użyciu gcc. Jestem zaznajomiony z 32-bitowym zestawem x86 (w środowisku MS-DOS), ale jestem początkującym w 64-bitowym zespole x86 i ogólnie w programowaniu montażu Linuksa.

Ten projekt jest przeznaczony do użytku produkcyjnego (potrzebuję działającego debugera bez źródła), ale próbuję również nauczyć się, jak wykonać konwersję 32-bitową na 64-bitową. Jeśli to możliwe, staram się znaleźć uniwersalny sposób na konwersję 32-bitową na 64-bitową, która mogłaby być wykonana w dowolnym 32-bitowym programie z użyciem wyrażeń regularnych (aby można było zautomatyzować). Wiem, że nie istnieje żadne ogólne rozwiązanie (kod 64-bitowy może zająć więcej miejsca niż kod 32-bitowy itp. I zużywać więcej stosu itp.), Ale nawet w takim przypadku automatycznie skonwertowany kod posłużyłby za punkt wyjścia.

Pomysł polegałby na zachowaniu 8-bitowych i 16-bitowych operandów jako takich i zastąpieniu 32-bitowych argumentów operandami 64-bitowymi. Takie podejście naturalnie zawiedzie, jeślipushw %ax; pushw %bx; popl %ecx jest zastąpiony przezpushw %ax; pushw %bx; popq %rcx, ale dobrze zachowane programy zazwyczaj tego nie robiąpush dwa 16-bitowe operandy, a następniepop jeden 32-bitowy operand, czy oni?

Oto dotychczasowe konwersje:

Edytować: Naprawić:pusha / pushad mogą być zastąpione przez kolejnepush'es, bopusha / pushad polecenia przesuwają wartośćsp / esp przed rzeczywisty nacisksp, ipush sp działa w ten sam sposób w 286+, ale inaczej w 8088/8086Baza danych języka montażu. Ta różnica nie stanowi tutaj problemu (dla kodu 386+).pusha ipushad można zatem zastąpić kolejnympush polecenia.

Alternatywą jest podobnie jak wOpenSolaris ”privregs.h kod.

Edytować: Poprawka: użyj 64-bitowego adresowania pamięci dla wszystkich poleceń.

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

Edytować: Poprawka: prawidłowa alternatywa (użycielea), zauważ, że procesory x86 są 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.

Edytować: Poprawka: poprawna alternatywa (użycielea):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.

Edytować: Naprawić:popa ipopad pop wartośćsp / esp ale odrzuć to (Zestaw instrukcji Intela - popa / popad). Chodźmypop to dobx / 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.

Edytować: push rejestrów segmentowych, np.pushw %ds ->pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax.

Edytować: pop rejestrów segmentowych, np.popw %ds ->pushw %ax; movw 2(%rsp), %ax; movw %ax, %ds; popw %ax.

Edytować: inc %reg16 ->add $1, %reg16, np.inc %ax ->add $1, %ax.

Edytować: dec %reg16 ->sub $1, %reg16, np.dec %ax ->sub $1, %ax.

Edytować: inc %reg32 ->add $1, %reg64, np.inc %eax ->add $1, %rax.

Edytować: dec %reg32 ->sub $1, %reg64, np.dec %eax ->sub $1, %rax.

Edytować: aaa ->?

Edytować: aad ->?

Edytować: aam ->?

Edytować: aas ->?

Edytować: arpl ->?

Edytować: bound ->?

Edytować: daa ->?

Edytować: das ->?

Edytować: lahf ->?

Edytować: sahf ->?

Edytować Poprawka: dowolne polecenie z bezpośrednim operandem, które nie pasuje do 32-bitowego rozmiaru operandu w trybie 64-bitowym, np.pushl $0xDEADBEEF ->pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax.

ret z bezpośrednim operandem: myślę, że w tym przypadku kod źródłowy musi zostać cofnięty, aby zobaczyć rozmiary ostatniegopushed operandów i działaj odpowiednio, np.pushl %eax; ret 4 ->pushq %rax; ret 8.

Edytować:: wezwania: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 (Uwaga: 32-bitowe wywołania systemowe mogą mieć więcej niż 6 parametrów, 6 w rejestrach, a reszta w stosie, 64-bitowe wywołania systemowe nigdy nie mogą mieć więcej niż 6 parametrów).

Edytować: Co jeszcze należy wziąć pod uwagę? Jakie inne konwersje byłyby potrzebne do konwersji kodu 32-bitowego na kod 64-bitowy (do uruchomienia w trybie długim)?

questionAnswers(0)

yourAnswerToTheQuestion