CodeBlanks Logo Icon CodeBlanks

Operand

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 == 11

Adlandı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 çevirme

Uygulama 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

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

Örnek çözüm

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

Soru
asm!(
    "mov {o}, {a}",
    a = in(reg) 5u64,
    o = ____(reg) t,
);
Cevap
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ı

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