Options
- Rust kursu
- Uzman
- Ders 28/46
- 4 dk
pure, nomem, nostack options'larını kullanırsın.
Options
Varsayılan olarak derleyici, assembly bloğunun belleği okuyup yazabileceğini, yığını kullanabileceğini ve yan etkileri olduğunu varsayar; bu, optimizasyonu kısıtlar. options(..) ile daha güçlü vaatler verilir:
let y: u64;
unsafe {
asm!(
"lea {o}, [{a} + {a}*2]", // o = a * 3
a = in(reg) x,
o = lateout(reg) y,
options(pure, nomem, nostack),
);
}pure: yan etkisi yok, çıktı yalnızca girdilere bağlı; sonuç kullanılmazsa blok silinebilir.nomem: belleğe dokunmaz.nostack: yığına yazmaz.
lea ile hızlı aritmetik
lea (load effective address) aslında bellek okumaz; adres hesaplama donanımını kullanarak a + b*k (k = 1, 2, 4, 8) biçiminde toplama ve çarpmayı tek talimatta yapar. Derleyiciler x * 3, x * 5 gibi çarpımları sıklıkla böyle üretir. Bu da çoğu zaman elle assembly'ye gerek olmadığını gösterir: x * 3 yazmak aynı talimatı üretir.
// derleyicinin x * 3 için ürettiği tipik kod:
// lea rax, [rdi + rdi*2]Uygulama Üç katı
x86-64 için lea ve options(pure, nomem, nostack) kullanan fn uc_kat(x: u64) -> u64 yaz (diğer mimarilerde x * 3). uc_kat(5) sonucunu yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
#[cfg(target_arch = "x86_64")]
fn uc_kat(x: u64) -> u64 {
let y: u64;
// SAFETY: lea belleğe erişmez; seçenekler doğrudur.
unsafe {
std::arch::asm!(
"lea {o}, [{a} + {a}*2]",
a = in(reg) x,
o = lateout(reg) y,
options(pure, nomem, nostack),
);
}
y
}
#[cfg(not(target_arch = "x86_64"))]
fn uc_kat(x: u64) -> u64 {
x * 3
}
fn main() {
println!("{}", uc_kat(5));
}Beklenen çıktı
15
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Belleğe yazan bir bloğa <code>nomem</code> denirse ne olur?
- Derleme hatası
- Yavaşlar
- Bir şey olmaz
- Tanımsız davranış: derleyici bellek değerlerinin değişmediğini varsayar Doğru cevap
Açıklama: Seçenekler derleyiciye verilen sözlerdir ve denetlenmez; yanlış söz, yanlış optimizasyon demektir.
2 Saf blok
asm!(
"lea {o}, [{a} + {a}*2]",
a = in(reg) x,
o = lateout(reg) y,
options(____, nomem, nostack),
);
asm!(
"lea {o}, [{a} + {a}*2]",
a = in(reg) x,
o = lateout(reg) y,
options(pure, nomem, nostack),
);
Açıklama: pure, bloğun yan etkisiz olduğunu ve yalnızca girdilere bağlı sonuç ürettiğini bildirir.
3 Seçenek ve vaadi
| Kavram | Anlamı |
|---|---|
pure |
Yan etki yok |
nomem |
Belleğe dokunmaz |
nostack |
Yığına yazmaz |
readonly |
Belleği yalnızca okur |