CodeBlanks Logo Icon CodeBlanks

Özet - Inline assembly

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

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
#[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ı

Soru
asm!("bswap {0:____}", inout(reg) x, options(pure, nomem, nostack));
Cevap
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ığı

Uzman bölümündeki tüm dersler