Hal pertama yang Anda butuhkan adalah sesuatu seperti file ini . Ini adalah database instruksi untuk prosesor x86 yang digunakan oleh assembler NASM (yang saya bantu tulis, meskipun bukan bagian yang benar-benar menerjemahkan instruksi). Mari kita pilih garis arbitrer dari database:
ADD rm32,imm8 [mi: hle o32 83 /0 ib,s] 386,LOCK
Apakah ini berarti bahwa itu menggambarkan instruksi ADD
. Ada beberapa varian dari instruksi ini, dan yang spesifik yang sedang dijelaskan di sini adalah varian yang mengambil register 32-bit atau alamat memori dan menambahkan nilai 8-bit langsung (yaitu konstanta yang langsung dimasukkan dalam instruksi). Contoh instruksi perakitan yang akan menggunakan versi ini adalah ini:
add eax, 42
Sekarang, Anda perlu mengambil input teks dan menguraikannya menjadi instruksi dan operan individual. Untuk instruksi di atas, ini mungkin akan menghasilkan struktur yang berisi instruksi ADD
,, dan array operan (referensi ke register EAX
dan nilai 42
). Setelah Anda memiliki struktur ini, Anda menjalankan melalui database instruksi dan menemukan baris yang cocok dengan nama instruksi dan jenis operan. Jika Anda tidak menemukan kecocokan, itu adalah kesalahan yang perlu disajikan kepada pengguna ("kombinasi opcode dan operan ilegal" atau yang serupa adalah teks yang biasa).
Setelah kami mendapatkan baris dari database, kami melihat kolom ketiga, yang untuk instruksi ini adalah:
[mi: hle o32 83 /0 ib,s]
Ini adalah serangkaian instruksi yang menjelaskan cara membuat instruksi kode mesin yang diperlukan:
- Ini
mi
adalah deskripsi operan: satu operan modr/m
(register atau memori) (yang berarti kita harus menambahkan modr/m
byte ke akhir instruksi, yang akan kita bahas nanti) dan satu lagi merupakan instruksi langsung (yang akan digunakan dalam deskripsi instruksi).
- Berikutnya adalah
hle
. Ini mengidentifikasi bagaimana kami menangani awalan "kunci". Kami belum menggunakan "kunci", jadi kami abaikan.
- Berikutnya adalah
o32
. Ini memberitahu kita bahwa jika kita merakit kode untuk format output 16-bit, instruksi tersebut membutuhkan awalan override ukuran operan. Jika kami memproduksi output 16-bit, kami akan menghasilkan awalan sekarang ( 0x66
), tapi saya akan menganggap kami tidak dan melanjutkan.
- Berikutnya adalah
83
. Ini adalah byte literal dalam heksadesimal. Kami memproduksinya.
Berikutnya adalah /0
. Ini menentukan beberapa bit tambahan yang akan kita butuhkan dalam modr / m bytem, dan menyebabkan kita menghasilkannya. The modr/m
byte digunakan untuk register encode atau referensi memori tidak langsung. Kami memiliki satu operan seperti itu, sebuah register. Register memiliki nomor, yang ditentukan dalam file data lain :
eax REG_EAX reg32 0
Kami memeriksa apakah reg32
setuju dengan ukuran instruksi yang diperlukan dari basis data asli (memang). Ini 0
adalah nomor register. Sebuah modr/m
byte adalah struktur data yang ditentukan oleh prosesor, yang terlihat seperti ini:
(most significant bit)
2 bits mod - 00 => indirect, e.g. [eax]
01 => indirect plus byte offset
10 => indirect plus word offset
11 => register
3 bits reg - identifies register
3 bits rm - identifies second register or additional data
(least significant bit)
Karena kami bekerja dengan register, mod
isiannya adalah 0b11
.
- The
reg
lapangan jumlah register yang kami gunakan,0b000
- Karena hanya ada satu register dalam instruksi ini, kita perlu mengisi kolom
rm
dengan sesuatu. Untuk itulah data tambahan ditentukan /0
, jadi kami letakkan itu di rm
bidang 0b000
,.
- The
modr/m
Oleh karena itu byte 0b11000000
atau 0xC0
. Kami menampilkan ini.
- Berikutnya adalah
ib,s
. Ini menentukan byte langsung yang ditandatangani. Kami melihat operan dan perhatikan kami memiliki nilai langsung yang tersedia. Kami mengonversinya menjadi byte yang ditandatangani dan mengeluarkannya ( 42
=> 0x2A
).
Oleh karena itu instruksi dirakit lengkap: 0x83 0xC0 0x2A
. Kirim ke modul output Anda, bersama dengan catatan bahwa tidak ada byte yang merupakan referensi memori (modul output mungkin perlu tahu jika mereka melakukannya).
Ulangi untuk setiap instruksi. Pantau label sehingga Anda tahu apa yang harus disisipkan saat direferensikan. Tambahkan fasilitas untuk makro dan arahan yang diteruskan ke modul output file objek Anda. Dan ini pada dasarnya cara kerja assembler.