Rust
Ö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.
Örnek çözümü göster
#[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());
}
Kendini test et
-
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
- Yalnızca derlenmesi
- Yorum satırı eklemek
Cevabı göster
Sonucu aynı işi yapan saf Rust sürümüyle karşılaştırmak — Referans uygulama hem yedek yol hem de test kâhinidir (oracle).
-
32 bit yazmaç adı
asm!("bswap {0:____}", inout(reg) x, options(pure, nomem, nostack));
Cevabı göster
asm!("bswap {0:e}", inout(reg) x, options(pure, nomem, nostack));
-
Grubun özeti
- asm!
- Satır içi talimat
- inout
- Girdi + çıktı
- options(pure)
- Yan etkisiz vaadi
- swap_bytes
- Saf Rust karşılığı
Sıradaki ders: no_std