Ada beberapa operasi yang hanya dapat Anda lakukan dengan DI / SI (atau rekannya yang diperluas, jika Anda tidak mempelajari ASM pada tahun 1985). Diantaranya adalah
REP STOSB
REP MOVSB
REP SCASB
Yaitu, operasi untuk penyimpanan, pemuatan, dan pemindaian berulang (= massal). Apa yang Anda lakukan adalah mengatur SI dan / atau DI untuk menunjuk ke salah satu atau kedua operan, mungkin menghitung di CX dan kemudian mari kita rip. Ini adalah operasi yang bekerja pada sekumpulan byte pada satu waktu, dan mereka semacam menempatkan CPU secara otomatis. Karena Anda tidak secara eksplisit mengkodekan loop, mereka melakukan tugasnya dengan lebih efisien (biasanya) daripada loop berkode tangan.
Untuk berjaga-jaga jika Anda bertanya-tanya: Bergantung pada bagaimana Anda mengatur operasi, penyimpanan berulang dapat menjadi sesuatu yang sederhana seperti memasukkan nilai 0 ke dalam blok memori yang berdekatan; MOVSB digunakan, menurut saya, untuk menyalin data dari satu buffer (yah, sekumpulan byte) ke buffer lainnya; dan SCASB digunakan untuk mencari byte yang cocok dengan beberapa kriteria pencarian (Saya tidak yakin apakah itu hanya mencari persamaan, atau apa - Anda dapat mencarinya :))
Tip pengoptimalan dari masa lalu: rep stosw jauh lebih cepat daripada rep stosb , jadi jika menyalin dua dan dua byte sesuai dengan apa yang Anda coba lakukan, gunakan itu sebagai gantinya dalam kode assembly 16-bit x86 yang dioptimalkan secara manual ...
Alexander
88
SI= Indeks Sumber DI= Indeks Tujuan
Seperti yang ditunjukkan orang lain, mereka memiliki kegunaan khusus dengan instruksi string. Untuk pemrograman mode real, ESregister segmen harus digunakan dengan DIdan DSdengan SIas in
movsb es:di, ds:si
SI dan DI juga dapat digunakan sebagai register indeks tujuan umum. Misalnya Ckode sumber
where ebp+12contains argv, ebxis j, dan edihas srcidx. Perhatikan instruksi ketiga menggunakan edimulitplied dengan 4 dan menambahkan ebpoffset dengan 0x54 (lokasi srcp); tanda kurung di sekitar alamat menunjukkan tipu muslihat.
Meskipun saya tidak dapat mengingat di mana saya melihatnya, tetapi ini menegaskan sebagian besar, dan ini (slide 17) lainnya:
Mereka terlihat seperti register tujuan umum, tetapi ada sejumlah instruksi yang (secara tidak terduga?) Menggunakan salah satunya — tetapi yang mana? — Secara implisit.
Selain operasi string (MOVS / INS / STOS / CMPS / SCASB / W / D / Q dll.) Yang disebutkan dalam jawaban lain, saya ingin menambahkan bahwa ada juga instruksi perakitan x86 yang lebih "modern" yang secara implisit digunakan di setidaknya EDI / RDI:
Instruksi SSE2 MASKMOVDQU(dan AVX yang akan datang VMASKMOVDQU) secara selektif menulis byte dari register XMM ke memori yang ditunjukkan oleh EDI / RDI.
Selain register yang digunakan untuk operasi massal, register berguna karena propertinya dipertahankan melalui pemanggilan fungsi (call-preserved) dalam konvensi pemanggilan 32-bit. ESI, EDI, EBX, EBP, ESP dipertahankan panggilan sedangkan EAX, ECX dan EDX tidak dipertahankan panggilan. Register yang dipertahankan dengan panggilan dipatuhi oleh fungsi perpustakaan C dan nilainya tetap ada melalui panggilan fungsi perpustakaan C.
Jeff Duntemann dalam buku bahasa assembly-nya memiliki contoh kode assembly untuk mencetak argumen baris perintah. Kode menggunakan esi dan edi untuk menyimpan penghitung karena mereka tidak akan diubah oleh printf fungsi perpustakaan C. Untuk register lain seperti eax, ecx, edx, tidak ada jaminan tidak akan digunakan oleh fungsi perpustakaan C.
Lihat bagian 12.8 Bagaimana C melihat Argumen Baris Perintah.
Perhatikan bahwa konvensi panggilan 64-bit berbeda dari konvensi panggilan 32-bit, dan saya tidak yakin apakah register ini dipertahankan panggilan atau tidak.
Saya belum pernah mendengar "sakral" digunakan untuk menggambarkan apa yang kebanyakan orang sebut "volatile" / "non-volatile", atau "callee-saving" vs "caller-saving". Saya suka "panggilan-dipertahankan" / "panggilan-clobbered", karena tidak berarti bahwa mereka benar-benar disimpan di mana pun. Bagaimanapun, ESI / RSI dan EDI / RDI tidak disimpan dalam panggilan di x86-64 System V ABI.
Peter Cordes
Selain itu, Anda lupa mencantumkan EBP dan ESP sebagai panggilan yang dipertahankan dalam konvensi panggilan 32-bit yang umum.
Peter Cordes
1
Bagaimanapun, itu poin yang cukup bagus. Dalam kode sebenarnya, Anda lebih cenderung memilih EDI / ESI untuk sesuatu yang didasarkan pada alasan konvensi panggilan daripada karena alasan tersebut khusus untuk instruksi apa pun.
Peter Cordes
Saya suka panggilan dipertahankan. Saya telah memperbarui jawabannya dengan yang sama. Terima kasih atas reviewnya.
Jawaban:
Ada beberapa operasi yang hanya dapat Anda lakukan dengan DI / SI (atau rekannya yang diperluas, jika Anda tidak mempelajari ASM pada tahun 1985). Diantaranya adalah
Yaitu, operasi untuk penyimpanan, pemuatan, dan pemindaian berulang (= massal). Apa yang Anda lakukan adalah mengatur SI dan / atau DI untuk menunjuk ke salah satu atau kedua operan, mungkin menghitung di CX dan kemudian mari kita rip. Ini adalah operasi yang bekerja pada sekumpulan byte pada satu waktu, dan mereka semacam menempatkan CPU secara otomatis. Karena Anda tidak secara eksplisit mengkodekan loop, mereka melakukan tugasnya dengan lebih efisien (biasanya) daripada loop berkode tangan.
Untuk berjaga-jaga jika Anda bertanya-tanya: Bergantung pada bagaimana Anda mengatur operasi, penyimpanan berulang dapat menjadi sesuatu yang sederhana seperti memasukkan nilai 0 ke dalam blok memori yang berdekatan; MOVSB digunakan, menurut saya, untuk menyalin data dari satu buffer (yah, sekumpulan byte) ke buffer lainnya; dan SCASB digunakan untuk mencari byte yang cocok dengan beberapa kriteria pencarian (Saya tidak yakin apakah itu hanya mencari persamaan, atau apa - Anda dapat mencarinya :))
Itulah sebagian besar dari tujuan reg itu.
sumber
SI
= Indeks SumberDI
= Indeks TujuanSeperti yang ditunjukkan orang lain, mereka memiliki kegunaan khusus dengan instruksi string. Untuk pemrograman mode real,
ES
register segmen harus digunakan denganDI
danDS
denganSI
as inSI dan DI juga dapat digunakan sebagai register indeks tujuan umum. Misalnya
C
kode sumberdikompilasi menjadi
where
ebp+12
containsargv
,ebx
isj
, danedi
hassrcidx
. Perhatikan instruksi ketiga menggunakanedi
mulitplied dengan 4 dan menambahkanebp
offset dengan 0x54 (lokasisrcp
); tanda kurung di sekitar alamat menunjukkan tipu muslihat.Meskipun saya tidak dapat mengingat di mana saya melihatnya, tetapi ini menegaskan sebagian besar, dan ini (slide 17) lainnya:
AX
= akumulator = akumulatorDX
kata gandaCX
= counterBX
= basis registerMereka terlihat seperti register tujuan umum, tetapi ada sejumlah instruksi yang (secara tidak terduga?) Menggunakan salah satunya — tetapi yang mana? — Secara implisit.
sumber
Opcode seperti MOVSB dan MOVSW yang secara efisien menyalin data dari memori yang ditunjukkan oleh ESI ke memori yang ditunjuk oleh EDI. Jadi,
sumber
Selain operasi string (MOVS / INS / STOS / CMPS / SCASB / W / D / Q dll.) Yang disebutkan dalam jawaban lain, saya ingin menambahkan bahwa ada juga instruksi perakitan x86 yang lebih "modern" yang secara implisit digunakan di setidaknya EDI / RDI:
Instruksi SSE2
MASKMOVDQU
(dan AVX yang akan datangVMASKMOVDQU
) secara selektif menulis byte dari register XMM ke memori yang ditunjukkan oleh EDI / RDI.sumber
Selain register yang digunakan untuk operasi massal, register berguna karena propertinya dipertahankan melalui pemanggilan fungsi (call-preserved) dalam konvensi pemanggilan 32-bit. ESI, EDI, EBX, EBP, ESP dipertahankan panggilan sedangkan EAX, ECX dan EDX tidak dipertahankan panggilan. Register yang dipertahankan dengan panggilan dipatuhi oleh fungsi perpustakaan C dan nilainya tetap ada melalui panggilan fungsi perpustakaan C.
Jeff Duntemann dalam buku bahasa assembly-nya memiliki contoh kode assembly untuk mencetak argumen baris perintah. Kode menggunakan esi dan edi untuk menyimpan penghitung karena mereka tidak akan diubah oleh printf fungsi perpustakaan C. Untuk register lain seperti eax, ecx, edx, tidak ada jaminan tidak akan digunakan oleh fungsi perpustakaan C.
https://www.amazon.com/Assembly-Language-Step-Step-Programming/dp/0470497025
Lihat bagian 12.8 Bagaimana C melihat Argumen Baris Perintah.
Perhatikan bahwa konvensi panggilan 64-bit berbeda dari konvensi panggilan 32-bit, dan saya tidak yakin apakah register ini dipertahankan panggilan atau tidak.
sumber