Özet - Inline assembly
- Rust kursu
- Uzman
- Ders 30/46
- 5 dk
asm!, in/out ve options'ı birleştirerek rdtsc ile zaman okursun.
Inline assembly özeti
asm! unsafe içinde işlemci talimatları yazar. Operandlar: in, out, inout, lateout; yazmaç sınıfı (reg) ya da açık yazmaç ("rax"). Bozulan yazmaçlar out("..") _ ya da clobber_abi ile bildirilir. options(pure, nomem, nostack, readonly) optimizasyonu açar ama doğruluk sorumluluğu sendedir. Taşınabilirlik için #[cfg(target_arch)] ve yedek uygulama; çoğu durumda std::arch intrinsics ya da derleyici yeterlidir.
Bayt sırasını çevirmek
bswap, 32 ya da 64 bitlik bir değerin bayt sırasını tersine çevirir (big-endian ↔ little-endian). Rust'ta karşılığı swap_bytes'tır; sonucu onunla karşılaştırarak doğrulayabiliriz:
let mut x: u32 = 0x11223344;
unsafe {
asm!("bswap {0:e}", inout(reg) x, options(pure, nomem, nostack));
}
assert_eq!(x, 0x11223344u32.swap_bytes()); // 0x44332211{0:e}, 32 bitlik yazmaç adını (eax gibi) kullanmak içindir; u32 değerin üst 32 biti tanımsız kalabileceği için önemlidir.
Uygulama bswap ve doğrulama
x86-64 için bswap {0:e} kullanan fn ters_bayt(x: u32) -> u32 yaz (diğer mimarilerde x.swap_bytes()). 0x11223344 için sonucu {:#x} ile ve swap_bytes ile eşitliğini boşlukla yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
#[cfg(target_arch = "x86_64")]
fn ters_bayt(mut x: u32) -> u32 {
// SAFETY: bswap yalnızca operand yazmacını değiştirir.
unsafe {
std::arch::asm!("bswap {0:e}", inout(reg) x, options(pure, nomem, nostack));
}
x
}
#[cfg(not(target_arch = "x86_64"))]
fn ters_bayt(x: u32) -> u32 {
x.swap_bytes()
}
fn main() {
let y = ters_bayt(0x11223344);
println!("{:#x} {}", y, y == 0x11223344u32.swap_bytes());
}Beklenen çıktı
0x44332211 true
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Bir assembly bloğunun doğruluğunu test etmenin iyi yolu nedir?
- Test edilemez
- Sonucu aynı işi yapan saf Rust sürümüyle karşılaştırmak Doğru cevap
- Yalnızca derlenmesi
- Yorum satırı eklemek
Açıklama: Referans uygulama hem yedek yol hem de test kâhinidir (oracle).
2 32 bit yazmaç adı
asm!("bswap {0:____}", inout(reg) x, options(pure, nomem, nostack));
asm!("bswap {0:e}", inout(reg) x, options(pure, nomem, nostack));
Açıklama: :e değiştiricisi 32 bitlik yazmaç adını seçer.
3 Grubun özeti
| Kavram | Anlamı |
|---|---|
asm! |
Satır içi talimat |
inout |
Girdi + çıktı |
options(pure) |
Yan etkisiz vaadi |
swap_bytes |
Saf Rust karşılığı |