Arsitektur x86
Prosesor Intel x86 menggunakan arsitektur komputer set instruksi kompleks (CISC), yang berarti ada sejumlah besar register tujuan khusus alih-alih sejumlah besar register tujuan umum. Ini juga berarti bahwa instruksi tujuan khusus yang kompleks akan mendominasi.
Prosesor x86 melacak warisannya setidaknya sejauh prosesor Intel 8080 8-bit. Banyak kekhasan dalam set instruksi x86 disebabkan oleh kompatibilitas mundur dengan prosesor tersebut (dan dengan varian Zilog Z-80-nya).
Microsoft Win32 menggunakan prosesor x86 dalam mode datar 32-bit. Dokumentasi ini hanya akan berfokus pada mode datar.
Register
Arsitektur x86 terdiri dari daftar bilangan bulat yang tidak memiliki hak istimewa berikut.
eax |
Akumulator |
ebx |
Register dasar |
ecx |
Daftar penghitung |
edx |
Data register - dapat digunakan untuk akses port I/O dan fungsi aritmatika |
Esi |
Register indeks sumber |
Edi |
Daftar indeks tujuan |
ebp |
Register penunjuk dasar |
Esp |
Penunjuk tumpukan |
Semua register bilangan bulat adalah 32 bit. Namun, banyak dari mereka memiliki subregister 16-bit atau 8-bit.
kapak |
eax 16 bit rendah |
Bx |
Ebx 16 bit rendah |
cx |
Ekx 16 bit rendah |
Dx |
Edx 16 bit rendah |
Si |
Rendah 16 bit esi |
di |
16 bit rendah edi |
Bp |
Rendah 16 bit ebp |
Sp |
Rendah 16 bit esp |
Al |
8 bit rendah eax |
Ah |
8 bit teks tinggi |
Bl |
8 bit rendah ebx |
Bh |
Tinggi 8 bit bx |
Cl |
8 bit rendah ekx |
Ch |
Tinggi 8 bit cx |
Dl |
8 bit rendah edx |
Dh |
Tinggi 8 bit dx |
Beroperasi pada sub-pendaftaran hanya memengaruhi subregister dan tidak ada bagian di luar sub-pendaftaran. Misalnya, menyimpan ke register kapak meninggalkan 16 bit tinggi dari register eax tidak berubah.
Saat menggunakan ? (Evaluasi Ekspresi) perintah, register harus diawali dengan tanda "at" ( @ ). Misalnya, Anda harus menggunakan ? @ax daripada ? ax. Ini memastikan bahwa debugger mengenali sumbu sebagai register daripada simbol.
Namun, (@) tidak diperlukan dalam perintah r (Registers ). Misalnya, r ax=5 akan selalu ditafsirkan dengan benar.
Dua register lainnya penting untuk status prosesor saat ini.
eip |
penunjuk instruksi |
flags |
flags |
Penunjuk instruksi adalah alamat instruksi yang dijalankan.
Register bendera adalah kumpulan bendera bit tunggal. Banyak instruksi mengubah bendera untuk menjelaskan hasil instruksi. Bendera-bendera ini kemudian dapat diuji dengan instruksi lompat bersyar. Lihat Bendera x86 untuk detailnya.
Konvensi Panggilan
Arsitektur x86 memiliki beberapa konvensi panggilan yang berbeda. Untungnya, mereka semua mengikuti aturan pelestarian register dan pengembalian fungsi yang sama:
Fungsi harus mempertahankan semua register, kecuali untuk eax, ecx, dan edx, yang dapat diubah di seluruh panggilan fungsi, dan esp, yang harus diperbarui sesuai dengan konvensi panggilan.
Register eax menerima nilai pengembalian fungsi jika hasilnya adalah 32 bit atau lebih kecil. Jika hasilnya adalah 64 bit, maka hasilnya disimpan dalam pasangan edx:eax .
Berikut ini adalah daftar konvensi panggilan yang digunakan pada arsitektur x86:
Win32 (__stdcall)
Parameter fungsi diteruskan pada tumpukan, didorong kanan ke kiri, dan penerima panggilan membersihkan tumpukan.
Panggilan metode C++ asli (juga dikenal sebagai thiscall)
Parameter fungsi diteruskan pada tumpukan, didorong kanan ke kiri, penunjuk "ini" diteruskan dalam register ecx , dan callee membersihkan tumpukan.
COM (__stdcall untuk panggilan metode C++)
Parameter fungsi diteruskan pada tumpukan, didorong kanan ke kiri, lalu penunjuk "ini" didorong pada tumpukan, dan kemudian fungsi dipanggil. Penerima panggilan membersihkan tumpukan.
__fastcall
Dua argumen DWORD-atau-smaller pertama diteruskan dalam ecx dan edx register. Parameter yang tersisa diteruskan pada tumpukan, didorong ke kanan ke kiri. Penerima panggilan membersihkan tumpukan.
__cdecl
Parameter fungsi diteruskan pada tumpukan, didorong kanan ke kiri, dan pemanggil membersihkan tumpukan. Konvensi panggilan __cdecl digunakan untuk semua fungsi dengan parameter panjang variabel.
Tampilan Debugger Daftar dan Bendera
Berikut adalah contoh tampilan register debugger:
eax=00000000 ebx=008b6f00 ecx=01010101 edx=ffffffff esi=00000000 edi=00465000
eip=77f9d022 esp=05cffc48 ebp=05cffc54 iopl=0 nv up ei ng nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000286
Dalam penelusuran kesalahan mode pengguna, Anda dapat mengabaikan iopl dan seluruh baris terakhir tampilan debugger.
Bendera x86
Dalam contoh sebelumnya, kode dua huruf di akhir baris kedua adalah bendera. Ini adalah register bit tunggal dan memiliki berbagai kegunaan.
Tabel berikut mencantumkan bendera x86:
Kode Bendera | Nama Bendera | Nilai | Status Bendera | Deskripsi |
---|---|---|---|---|
Tengah | Bendera Luapan | 0 1 | nvov | Tidak ada luapan - Luapan |
Df | Bendera Arah | 0 1 | updn | Arah ke atas - Arah ke bawah |
if | Bendera Interupsi | 0 1 | diei | Interupsi dinonaktifkan - Interupsi diaktifkan |
Sf | Tanda tangani Bendera | 0 1 | plng | Positif (atau nol) - Negatif |
zf | Bendera Nol | 0 1 | nzzr | Nonzero - Nol |
af | Bendera Carry Tambahan | 0 1 | naac | Tidak ada carry tambahan - Carry tambahan |
Pf | Bendera Paritas | 0 1 | pepo | Parity odd - Parity even |
Cf | Bawa Bendera | 0 1 | nccy | Tidak ada carry - Carry |
tf | Bendera Trap | Jika tf sama dengan 1, prosesor akan menaikkan pengecualian STATUS_SINGLE_STEP setelah eksekusi satu instruksi. Bendera ini digunakan oleh debugger untuk menerapkan pelacakan langkah tunggal. Ini tidak boleh digunakan oleh aplikasi lain. | ||
iopl | Tingkat Hak Istimewa I/O | Tingkat Hak Istimewa I/O Ini adalah bilangan bulat dua-bit, dengan nilai antara nol dan 3. Ini digunakan oleh sistem operasi untuk mengontrol akses ke perangkat keras. Ini tidak boleh digunakan oleh aplikasi. |
Ketika register ditampilkan sebagai hasil dari beberapa perintah di jendela Perintah Debugger, itu adalah status bendera yang ditampilkan. Namun, jika Anda ingin mengubah bendera menggunakan perintah r (Registers), Anda harus merujuknya dengan kode bendera.
Di jendela Daftar WinDbg, kode bendera digunakan untuk melihat atau mengubah bendera. Status bendera tidak didukung.
Berikut adalah contohnya. Di tampilan register sebelumnya, status bendera ng muncul. Ini berarti bahwa bendera tanda saat ini diatur ke 1. Untuk mengubah ini, gunakan perintah berikut:
r sf=0
Ini mengatur bendera tanda ke nol. Jika Anda melakukan tampilan register lain, kode status ng tidak akan muncul. Sebagai gantinya , kode status pl akan ditampilkan.
Bendera Tanda, Bendera Nol, dan Bendera Carry adalah bendera yang paling umum digunakan.
Kondisi
Kondisi menjelaskan status satu atau beberapa bendera. Semua operasi kondisional pada x86 dinyatakan dalam hal kondisi.
Perakitan menggunakan singkatan satu atau dua huruf untuk mewakili kondisi. Kondisi dapat diwakili oleh beberapa singkatan. Misalnya, AE ("di atas atau sama") adalah kondisi yang sama dengan NB ("tidak di bawah"). Tabel berikut ini mencantumkan beberapa kondisi umum dan maknanya.
Nama Kondisi | Bendera | Makna |
---|---|---|
Z |
ZF=1 |
Hasil operasi terakhir adalah nol. |
NZ |
ZF=0 |
Hasil operasi terakhir bukan nol. |
C |
CF=1 |
Operasi terakhir memerlukan carry atau pinjam. (Untuk bilangan bulat yang tidak ditandatangani, ini menunjukkan luapan.) |
NC |
CF=0 |
Operasi terakhir tidak memerlukan carry atau pinjam. (Untuk bilangan bulat yang tidak ditandatangani, ini menunjukkan luapan.) |
S |
SF=1 |
Hasil operasi terakhir memiliki set bit tinggi. |
NS |
SF=0 |
Hasil operasi terakhir memiliki bit tinggi yang jelas. |
O |
OF=1 |
Ketika diperlakukan sebagai operasi bilangan bulat yang ditandatangani, operasi terakhir menyebabkan luapan atau aliran bawah. |
TIDAK |
OF=0 |
Ketika diperlakukan sebagai operasi bilangan bulat yang ditandatangani, operasi terakhir tidak menyebabkan luapan atau aliran bawah. |
Kondisi juga dapat digunakan untuk membandingkan dua nilai. Instruksi cmp membandingkan dua operannya, lalu mengatur bendera seolah-olah dikurangi satu operand dari yang lain. Kondisi berikut dapat digunakan untuk memeriksa hasil nilai cmp1, value2.
Nama Kondisi | Bendera | Artinya setelah operasi CMP. |
---|---|---|
E |
ZF=1 |
value1 == value2. |
NE |
ZF=0 |
value1 != value2. |
GE NL | SF=OF |
value1>= value2. Nilai diperlakukan sebagai bilangan bulat yang ditandatangani. |
LE NG | ZF=1 atau SF!=OF |
value1<= value2. Nilai diperlakukan sebagai bilangan bulat yang ditandatangani. |
G NLE | ZF=0 dan SF=OF |
value1>value2. Nilai diperlakukan sebagai bilangan bulat yang ditandatangani. |
L NGE | SF!=OF |
value1<value2. Nilai diperlakukan sebagai bilangan bulat yang ditandatangani. |
AE NB | CF=0 |
value1>= value2. Nilai diperlakukan sebagai bilangan bulat yang tidak ditandatangani. |
BE NA | CF=1 atau ZF=1 |
value1<= value2. Nilai diperlakukan sebagai bilangan bulat yang tidak ditandatangani. |
A NBE | CF=0 dan ZF=0 |
value1>value2. Nilai diperlakukan sebagai bilangan bulat yang tidak ditandatangani. |
B NAE | CF=1 |
value1<value2. Nilai diperlakukan sebagai bilangan bulat yang tidak ditandatangani. |
Kondisi biasanya digunakan untuk bertindak berdasarkan hasil instruksi cmp atau pengujian . Contohnya,
cmp eax, 5
jz equal
membandingkan register eax dengan angka 5 dengan menghitung ekspresi (eax - 5) dan mengatur bendera sesuai dengan hasilnya. Jika hasil pengurangan adalah nol, maka bendera zr akan diatur, dan kondisi jz akan benar sehingga lompatan akan diambil.
Tipe Data
byte: 8 bit
word: 16 bit
dword: 32 bit
qword: 64 bit (termasuk floating-point doubles)
tword: 80 bit (termasuk floating-point extended doubles)
oword: 128 bit
Notasi
Tabel berikut menunjukkan notasi yang digunakan untuk menjelaskan instruksi bahasa perakitan.
Notasi | Makna |
---|---|
r, r1, r2... |
Register |
m |
Alamat memori (lihat bagian Mode Alamat yang berhasil untuk informasi selengkapnya.) |
#n |
Konstanta langsung |
r/m |
Daftar atau memori |
r/#n |
Mendaftarkan atau konstanta langsung |
r/m/#n |
Mendaftarkan, memori, atau konstanta langsung |
Cc |
Kode kondisi yang tercantum di bagian Kondisi sebelumnya. |
T |
"B", "W", atau "D" (byte, word atau dword) |
accT |
Akumulator Ukuran T: al jika T = "B", ax jika T = "W", atau eax jika T = "D" |
Mode Alamat
Ada beberapa mode alamat yang berbeda, tetapi semuanya mengambil formulir T ptr [expr], di mana T adalah beberapa jenis data (lihat bagian Jenis Data sebelumnya) dan expr adalah beberapa ekspresi yang melibatkan konstanta dan register.
Notasi untuk sebagian besar mode dapat disimpulkan tanpa banyak kesulitan. Misalnya, BYTE PTR [esi+edx*8+3] berarti "ambil nilai esi register, tambahkan delapan kali nilai register edx , tambahkan tiga, lalu akses byte pada alamat yang dihasilkan."
Pipelining
Pentium adalah masalah ganda, yang berarti dapat melakukan hingga dua tindakan dalam satu jam centang. Namun, aturan tentang kapan ia mampu melakukan dua tindakan sekaligus (dikenal sebagai pemasangan) sangat rumit.
Karena x86 adalah prosesor CISC, Anda tidak perlu khawatir tentang slot penundaan lompat.
Akses Memori yang Disinkronkan
Instruksi pemuatan, modifikasi, dan penyimpanan dapat menerima awalan kunci , yang memodifikasi instruksi sebagai berikut:
Sebelum mengeluarkan instruksi, CPU akan menghapus semua operasi memori yang tertunda untuk memastikan koherensi. Semua prefetch data ditinggalkan.
Saat mengeluarkan instruksi, CPU akan memiliki akses eksklusif ke bus. Ini memastikan atomitas operasi pemuatan/modifikasi/penyimpanan.
Instruksi xchg secara otomatis mematuhi aturan sebelumnya setiap kali bertukar nilai dengan memori.
Semua instruksi lainnya default ke nonlocking.
Prediksi Lompat
Lompatan tanpa syarat diprediksi akan diambil.
Lompatan kondisional diprediksi diambil atau tidak, tergantung pada apakah mereka diambil terakhir kali dieksekusi. Cache untuk merekam riwayat lompatan berukuran terbatas.
Jika CPU tidak memiliki catatan apakah lompatan bersyarkat diambil atau tidak diambil saat terakhir kali dijalankan, CPU memprediksi lompatan berskalakan mundur seperti yang diambil dan meneruskan lompatan bersyar seperti yang tidak diambil.
Alignment
Prosesor x86 akan secara otomatis memperbaiki akses memori yang tidak ditandatangani, dengan penalti performa. Tidak ada pengecualian yang dimunculkan.
Akses memori dianggap selaras jika alamat adalah bilangan bulat kelipatan ukuran objek. Misalnya, semua akses BYTE diselaraskan (semuanya adalah bilangan bulat kelipatan 1), akses WORD ke alamat genap selaras, dan alamat DWORD harus kelipatan 4 agar selaras.
Awalan kunci tidak boleh digunakan untuk akses memori yang tidak ditandatangani.