Menggunakan dan Mempertahankan Pendaftaran di Rakitan Sebaris
Khusus Microsoft
Secara umum, Anda tidak boleh berasumsi bahwa register akan memiliki nilai tertentu ketika __asm
blok dimulai. Nilai register tidak dijamin akan dipertahankan di seluruh blok terpisah __asm
. Jika Anda mengakhiri blok kode sebaris dan memulai yang lain, Anda tidak dapat mengandalkan register di blok kedua untuk mempertahankan nilainya dari blok pertama. Blok __asm
mewarisi nilai register apa pun yang dihasilkan dari alur kontrol normal.
Jika Anda menggunakan __fastcall
konvensi panggilan, pengkompilasi meneruskan argumen fungsi dalam register alih-alih pada tumpukan. Ini dapat membuat masalah dalam fungsi dengan __asm
blok karena fungsi tidak memiliki cara untuk mengetahui parameter mana yang mendaftar. Jika fungsi kebetulan menerima parameter di EAX dan segera menyimpan sesuatu yang lain di EAX, parameter asli hilang. Selain itu, Anda harus mempertahankan register ECX dalam fungsi apa pun yang dideklarasikan dengan __fastcall
.
Untuk menghindari konflik register tersebut __fastcall
, jangan gunakan konvensi untuk fungsi yang berisi __asm
blok. Jika Anda menentukan __fastcall
konvensi secara global dengan opsi pengkompilasi /Gr, nyatakan setiap fungsi yang __asm
berisi blok dengan __cdecl
atau __stdcall
. (Atribut __cdecl
memberi tahu pengkompilasi untuk menggunakan konvensi panggilan C untuk fungsi tersebut.) Jika Anda tidak mengkompilasi dengan /Gr, hindari mendeklarasikan fungsi dengan __fastcall
atribut .
Saat menggunakan __asm
untuk menulis bahasa assembly dalam fungsi C/C++, Anda tidak perlu mempertahankan pendaftaran EAX, EBX, ECX, EDX, ESI, atau EDI. Misalnya, di POWER2. Contoh C dalam Fungsi Penulisan dengan Rakitan Sebaris, power2
fungsi tidak mempertahankan nilai dalam register EAX. Namun, menggunakan register ini akan memengaruhi kualitas kode karena alokator register tidak dapat menggunakannya untuk menyimpan nilai di seluruh __asm
blok. Selain itu, dengan menggunakan EBX, ESI atau EDI dalam kode perakitan sebaris, Anda memaksa kompilator untuk menyimpan dan memulihkan register tersebut dalam prolog fungsi dan epilog.
Anda harus mempertahankan register lain yang Anda gunakan (seperti DS, SS, SP, BP, dan daftar bendera) untuk cakupan __asm
blok. Anda harus mempertahankan register ESP dan EBP kecuali Anda memiliki beberapa alasan untuk mengubahnya (misalnya untuk beralih tumpukan). Lihat juga Mengoptimalkan Rakitan Sebaris.
Beberapa jenis SSE memerlukan perataan tumpukan delapan byte, memaksa pengkompilasi untuk memancarkan kode perataan tumpukan dinamis. Agar dapat mengakses variabel lokal dan parameter fungsi setelah perataan, pengkompilasi mempertahankan dua penunjuk bingkai. Jika compiler melakukan kelalaian pointer bingkai (FPO), kompilator akan menggunakan EBP dan ESP. Jika compiler tidak melakukan FPO, ia akan menggunakan EBX dan EBP. Untuk memastikan kode berjalan dengan benar, jangan ubah EBX dalam kode asm jika fungsi memerlukan perataan tumpukan dinamis karena dapat memodifikasi penunjuk bingkai. Pindahkan jenis selaras delapan byte dari fungsi, atau hindari menggunakan EBX.
Catatan
Jika kode rakitan sebaris Anda mengubah bendera arah menggunakan instruksi STD atau CLD, Anda harus memulihkan bendera ke nilai aslinya.
END Khusus Microsoft
Baca juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk