Gunakan penyandian bentuk pendek kasus khusus untuk AL / AX / EAX, dan formulir pendek lainnya dan instruksi byte tunggal
Contoh mengasumsikan mode 32/64-bit, di mana ukuran operan default adalah 32 bit. Awalan ukuran operan mengubah instruksi ke AX alih-alih EAX (atau terbalik dalam mode 16-bit).
inc/dec
register (selain 8-bit): inc eax
/ dec ebp
. (Bukan x86-64: 0x4x
byte opcode digunakan kembali sebagai awalan REX, jadi inc r/m32
adalah satu-satunya penyandian.)
8-bit inc bl
adalah 2 byte, menggunakan inc r/m8
opcode + ModR / M operand encoding . Jadi gunakan inc ebx
untuk menambah bl
, jika aman. (mis. jika Anda tidak memerlukan hasil ZF dalam kasus di mana byte atas mungkin tidak nol).
scasd
: e/rdi+=4
, mensyaratkan bahwa register menunjuk ke memori yang dapat dibaca. Terkadang bermanfaat bahkan jika Anda tidak peduli dengan hasil FLAGS (seperti cmp eax,[rdi]
/ rdi+=4
). Dan dalam mode 64-bit, scasb
dapat berfungsi sebagai 1-byteinc rdi
, jika lodsb atau stosb tidak berguna.
xchg eax, r32
: Ini adalah di mana 0x90 NOP berasal dari: xchg eax,eax
. Contoh: mengatur ulang 3 register dengan dua xchg
instruksi dalam cdq
/ idiv
loop untuk GCD dalam 8 byte di mana sebagian besar instruksi adalah single-byte, termasuk penyalahgunaan inc ecx
/ loop
bukannya test ecx,ecx
/jnz
cdq
: tandatangani-rentangkan EAX ke dalam EDX: EAX, yaitu menyalin bit EAX yang tinggi ke semua bit EDX. Untuk membuat nol dengan diketahui non-negatif, atau untuk mendapatkan 0 / -1 untuk ditambahkan / sub atau topeng. pelajaran sejarah x86: cltq
vs.movslq
, dan juga AT&T vs Intel mnemonics untuk ini dan yang terkait cdqe
.
lodsb / d : suka mov eax, [rsi]
/ rsi += 4
tanpa bendera yang rusak. (Dengan anggapan DF jelas, konvensi panggilan standar mana yang diperlukan pada entri fungsi.) Juga stosb / d, terkadang scas, dan lebih jarang bergerak / cmps.
push
/ pop reg
. misalnya dalam mode 64-bit, push rsp
/ pop rdi
adalah 2 byte, tetapi mov rdi, rsp
membutuhkan awalan REX dan 3 byte.
xlatb
ada, tetapi jarang bermanfaat. Tabel pencarian besar adalah sesuatu yang harus dihindari. Saya juga tidak pernah menemukan penggunaan untuk AAA / DAA atau instruksi paket-BCD atau 2-ASCII lainnya.
1-byte lahf
/ sahf
jarang bermanfaat. Anda bisa lahf
/ and ah, 1
sebagai alternatif setc ah
, tetapi biasanya tidak berguna.
Dan untuk CF secara khusus, ada sbb eax,eax
untuk mendapatkan 0 / -1, atau bahkan 1-byte yang tidak didokumentasikan tetapi didukung secara universal salc
(atur AL dari Carry) yang secara efektif tidak sbb al,al
mempengaruhi flag. (Dihapus di x86-64). Saya menggunakan SALC dalam Tantangan Penghargaan Pengguna # 1: Dennis ♦ .
1-byte cmc
/ clc
/ stc
(flip ("pelengkap"), jelas, atau set CF) jarang berguna, meskipun saya menemukan penggunaan untukcmc
penambahan presisi-tinggi dengan basis 10 ^ 9 potongan. Untuk mengatur / menghapus CF tanpa syarat, biasanya mengatur agar itu terjadi sebagai bagian dari instruksi lain, misalnya xor eax,eax
membersihkan CF dan juga EAX. Tidak ada instruksi yang setara untuk flag kondisi lain, hanya DF (arah string) dan IF (interupsi). Bendera carry khusus untuk banyak instruksi; shift mengaturnya, adc al, 0
dapat menambahkannya ke AL dalam 2 byte, dan saya sebutkan sebelumnya SALC tidak berdokumen.
std
Saya cld
jarang terlihat sepadan . Khususnya dalam kode 32-bit, lebih baik gunakan saja dec
pada pointer dan mov
atau sumber memori operan ke instruksi ALU daripada mengatur DF begitu lodsb
/ stosb
turun ke bawah bukan ke atas. Biasanya jika Anda perlu ke bawah sama sekali, Anda masih memiliki pointer lain naik, jadi Anda akan membutuhkan lebih dari satu std
dan cld
seluruh fungsi untuk menggunakan lods
/ stos
untuk keduanya. Sebagai gantinya, cukup gunakan instruksi string untuk arah ke atas. (Konvensi panggilan standar menjamin DF = 0 pada entri fungsi, sehingga Anda dapat menganggap itu gratis tanpa menggunakan cld
.)
8086 sejarah: mengapa pengkodean ini ada
Di asli 8086, AX sangat istimewa: petunjuk suka lodsb
/ stosb
, cbw
, mul
/ div
dan lain-lain menggunakannya secara implisit. Tentu saja masih demikian; x86 saat ini belum menjatuhkan opcodes 8086 (setidaknya tidak ada yang secara resmi didokumentasikan). Tetapi kemudian CPU menambahkan instruksi baru yang memberikan cara yang lebih baik / lebih efisien untuk melakukan sesuatu tanpa menyalin atau menukar mereka ke AX terlebih dahulu. (Atau ke EAX dalam mode 32-bit.)
misal 8086 tidak memiliki tambahan tambahan seperti movsx
/ movzx
untuk memuat atau memindahkan + sign-extended, atau 2 dan 3 operan imul cx, bx, 1234
yang tidak menghasilkan hasil setengah tinggi dan tidak memiliki operan implisit.
Juga, hambatan utama 8086 adalah instruksi-ambil, jadi mengoptimalkan ukuran kode penting untuk kinerja saat itu . Perancang ISA 8086 (Stephen Morse) menghabiskan banyak ruang pengkodean opcode pada case khusus untuk AX / AL, termasuk opcode khusus (E) AX / AL-tujuan untuk semua instruksi ALU- direct-src dasar , hanya opcode + direct tanpa byte ModR / M. 2-byte add/sub/and/or/xor/cmp/test/... AL,imm8
atau AX,imm16
atau (dalam mode 32-bit) EAX,imm32
.
Tetapi tidak ada kasus khusus untuk EAX,imm8
, sehingga pengkodean ModR / M reguler add eax,4
lebih pendek.
Asumsinya adalah jika Anda akan mengerjakan beberapa data, Anda akan menginginkannya di AX / AL, jadi bertukar register dengan AX adalah sesuatu yang mungkin ingin Anda lakukan, mungkin bahkan lebih sering daripada menyalin register ke AX dengan mov
.
Segala sesuatu tentang 8086 instruksi pengkodean mendukung paradigma ini, dari instruksi seperti lodsb/w
untuk semua pengkodean kasus khusus untuk segera dengan EAX hingga penggunaan implisitnya bahkan untuk penggandaan / pembagian.
Jangan terbawa; itu tidak otomatis menang untuk menukar semuanya ke EAX, terutama jika Anda perlu menggunakan segera dengan register 32-bit, bukan 8-bit. Atau jika Anda perlu interleave operasi pada beberapa variabel dalam register sekaligus. Atau jika Anda menggunakan instruksi dengan 2 register, tidak segera sama sekali.
Tetapi selalu ingat: apakah saya melakukan sesuatu yang lebih pendek di EAX / AL? Dapatkah saya mengatur ulang sehingga saya memiliki ini dalam AL, atau apakah saya saat ini mengambil keuntungan lebih baik dari AL dengan apa yang sudah saya gunakan untuk itu.
Campurkan operasi 8-bit dan 32-bit secara bebas untuk mengambil keuntungan kapan pun aman untuk melakukannya (Anda tidak perlu melakukan daftar lengkap atau apa pun).
push 200; pop edx
- 3 byte untuk inisialisasi.