Operand
- Rust kursu
- Uzman
- Ders 26/46
- 4 dk
in, out, inout operandlarını kullanırsın.
Operand
Operandlar Rust değişkenlerini assembly'ye bağlar:
in(reg) x: yalnızca girdi.out(reg) y: yalnızca çıktı; başlangıç değeri anlamsız.inout(reg) z: hem girdi hem çıktı.lateout(reg) y: tüm girdiler okunduktan sonra yazılan çıktı; derleyici bir girdinin yazmacını yeniden kullanabilir.
let t: u64;
unsafe {
asm!(
"mov {o}, {a}",
"add {o}, {b}",
a = in(reg) 5u64,
b = in(reg) 6u64,
o = out(reg) t,
);
}
// t == 11Adlandırılmış operandlar ({a}) birden çok satırlı kodu okunur kılar.
Yazmaç sınıfları
reg genel amaçlı yazmaç sınıfıdır. Diğer sınıflar: x86'da xmm_reg, ymm_reg (vektör), reg_byte (8 bit). Değerin boyutu yazmacın hangi parçasının kullanılacağını belirler; açıkça seçmek için şablon değiştiricileri vardır: {0:e} 32 bitlik eax gibi adı, {0:r} 64 bitlik rax gibi adı verir.
let mut x: u32 = 0x11223344;
unsafe { asm!("bswap {0:e}", inout(reg) x) }; // 32 bit bayt ters çevirmeUygulama Adlandırılmış operandlar
Yukarıdaki iki talimatlı örneği x86-64 için fn topla(a: u64, b: u64) -> u64 olarak yaz (diğer mimarilerde a + b). topla(5, 6) sonucunu yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
#[cfg(target_arch = "x86_64")]
fn topla(a: u64, b: u64) -> u64 {
let t: u64;
// SAFETY: yalnızca operand yazmaçlarını kullanır.
unsafe {
std::arch::asm!(
"mov {o}, {a}",
"add {o}, {b}",
a = in(reg) a,
b = in(reg) b,
o = out(reg) t,
);
}
t
}
#[cfg(not(target_arch = "x86_64"))]
fn topla(a: u64, b: u64) -> u64 {
a + b
}
fn main() {
println!("{}", topla(5, 6));
}Beklenen çıktı
11
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Yukarıdaki örnekte <code>o</code> için <code>lateout</code> kullanmak neden hatalı olabilir?
- Hatalı değildir
- o ilk talimatta yazılıyor ama b henüz okunmadı; derleyici o ile b'ye aynı yazmacı verebilir Doğru cevap
- lateout yoktur
- Daha yavaştır
Açıklama: lateout yalnızca tüm girdiler kullanıldıktan sonra yazılan çıktılar için güvenlidir.
2 Yalnızca çıktı
asm!(
"mov {o}, {a}",
a = in(reg) 5u64,
o = ____(reg) t,
);
asm!(
"mov {o}, {a}",
a = in(reg) 5u64,
o = out(reg) t,
);
Açıklama: out operandı yalnızca assembly'nin yazdığı bir değeri Rust'a taşır.
3 Operand ve yönü
| Kavram | Anlamı |
|---|---|
in(reg) x |
Rust → asm |
out(reg) y |
asm → Rust |
inout(reg) z |
İki yön |
lateout(reg) y |
Girdilerden sonra çıktı |