2012-11-11 7 views
5

Piszę kompilatora dla instrukcji procesorów x86/x64, a ja nie potrafię zrozumieć, co ludzie mają na myśli przez adres „przemieszczenia”. Na przykład instrukcja Add jest szczegółowo tutaj: http://www.c-jump.com/CIS77/CPU/x86/X77_0150_encoding_add_edx_displacement.htmx86/x64 Dodaj Przesunięcie adresowania

Po prostu próbuję wdrożyć instrukcję add, gdzie rejestr jest dodawany do normalnego adresu pamięci. Problem polega na tym, że adres jest "adresem przemieszczenia". Czy to oznacza, że ​​adres jest wartością podpisaną, która jest przesunięciem od lokalizacji instrukcji?

+3

Czy generujesz kod zespołu? Nie możesz wygenerować kodu C lub użyć LLVM? Lub emitować kod maszynowy za pomocą http://code.google.com/p/asmjit/ lub innych bibliotek? Czy dobrze rozumiesz zestaw instrukcji x86/64? Czy studiowałeś http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html –

Odpowiedz

9

w x86 Istnieje kilka różnych form operandów pośrednia

  1. [reg]
  2. [reg + przemieszczenie]
  3. [przemieszczenie]
  4. [reg * Stały + reg ]
  5. [reg * stała + reg + przesunięcie]

"Przesunięcie" jest po prostu stałą, która zostaje dodana do reszty adresu. W przypadkach, gdy nie ma komponentu adresu innego niż stała, nadal jest on nazywany "przesunięciem".Dotyczy to głównie spójności z innymi formularzami adresowymi.

Inny sposób wygląda na to, że wszystkie adresy są postaci

[reg * Stały + reg + przemieszczenie]

z każdym z elementów pozwalających na wartość 0.

Forma [przesunięcie] jest po prostu kodowaniem, w którym wszystkie elementy inne niż przesunięcie są zerowe.

Jako twórca kompilatora szczególnie interesujące są 2 ostatnie formularze. Ułatwiają kodowanie rzeczy takich jak pArray[index]->field + 1 w pojedynczej instrukcji.

+0

Ok, więc w jaki sposób [reg * constant + reg + displacement] zostaje zakodowana w instrukcji maszyny? Powiedzmy, że mam tablicę w miejscu pamięci 0x00000001 i chcę uzyskać dostęp do jej indeksu, który jest AL. Chyba chcę użyć instrukcji move i wykonać MOV AH 0x00000001 [AL]. Myślę, że to tylko [reg + przesunięcie]. Sekcja 6 tej strony pokazuje kodowanie bajtów R/M, ale jest to naprawdę mylące: http://www.c-jump.com/CIS77/CPU/x86/lecture.html –

+0

Spójrz na tom 2 podręcznika wywiadu. Każda instrukcja określa jej formy kodowania. Kodowanie formularzy z listą operandów r/m przyjmuje rejestr lub operandów pamięci w bajcie mod/rm. –

+0

Spójrz na tom 2 podręcznika wywiadu. Każda instrukcja określa jej formy kodowania. Kodowanie formularzy z listą operandów r/m przyjmuje rejestr lub operandów pamięci w bajcie mod/rm. W rozdziale 2 tomu 2, sekcja 2.1 znajduje się tabela pokazująca znaczenie modu r/m bajtu. Formularze z podanymi [-] [-] oznaczają kodowanie wykorzystujące bajt SIB. Adresowanie SIB ma postać reg * constant + reg. Niektóre formy bajtu mod/rm wskazują, że po bajcie SIB następuje przesunięcie. Te dają reg * constant + reg + constant forms. Istnieje tabela wyjaśniająca również SIB. –

3

Nie ma "specjalnego dodatku, który zajmuje przemieszczenie", strona jest niepotrzebnie myląca - jest to tylko część normalnego kodowania operandów pamięci.

add jest dość standardowe instrukcja, która jest zakodowana w ten sam sposób jak wszystkie Alu-OPS to: nie jest szczególnym przypadkiem za korzystanie al jako cel i natychmiastowe jako źródło (04 ib), używając ax/eax/rax jako cel i natychmiast jako źródło (+ 05 imm), trzy wersje add r/m, imm (jedna dla 8-bitowych miejsc docelowych, jedna dla szerszych miejsc docelowych i rozszerzone znakiem 8-bitowe źródło, jedna dla szerszych miejsc docelowych i szerokiego źródła), i oczywiście add r, r/m i add r/m, r.

To tylko specjalny przypadek add r, r/m, gdzie r/m ma postać przesunięcia: patrz uwaga # 1 z ModRM encoding.

Więc po prostu oznaczać add edx, [sdword]. (ale zmodularyzowali pole REG, edx odpowiada 010, nie 011)

+0

Aby dodać AL (8-bitowy rejestr 0) do lokalizacji pamięci 0x00000000, CPU zaakceptuje (w języku heksadecymalnym) 00 05 00000000? –

+0

@RyanBrown tak, to by działało – harold

4

Ta strona nie jest dokładna. "Dodanie, które ma przesunięcie", o którym mowa, odnosi się do postaci add r[16|32], r/m[16|32] lub add edx, [0xdisp], tak jak w przypadku wyjścia dezasemblera. Zakładając, że mówi o instrukcji ADD z opcode 0x03,

  • Kodowanie rejestru docelowego edx i określając przesunięcie 32-bitową równie skuteczny adres w bajcie Modr/M by nadać mu wartość 0x15 (patrz Intel ® 64 i IA-32 Architectures Software Developer's Manual Vol. 2, strona 41, tabela 2-2).
  • Efektem tej instrukcji jest dodanie DWORD adresem pamięci disp do treści edx.
  • Rzeczywiste kodowanie instrukcji będzie zatem: \x03\x15\x00\x00\x00\x01, dla przemieszczenia 1 bajtu.