パタヘネ1 読んでたら乗算、除算のアーキテクチャ実装が載っていたのでRustで書いてみました。
ビット演算だけで表現できるのすごいなほへーってなりました。またbit演算のいい練習になりました。
あとこの調子でいったらアセンブリ言語のインタプリタとか作れそう!(小並
低レイヤー全般全くの無知なので間違ってたりとかこうした方がいいとかあったらコメントしていただけると嬉しいです。
パタヘネまだ上巻しか読んでないけどわかりやすくて脳汁ブシャーってなるかなりいい本
struct Register {
hi: i32,
lo: i32
}
impl Register {
// 乗算
fn mult(&mut self, rs: &i32 , rt: &i32) {
let mut rt = *rt as i64;
for _ in 0..32 {
if rt & 1 == 1 {
rt += (*rs as i64) << 32;
}
rt >>= 1;
}
// hi: rtの上位32ビット
// lo: rtの下位32ビット
self.hi = (rt >> 32) as i32;
self.lo = rt as i32;
// オーバーフロー検知
// オーバーフローの条件 → hi と lo の符号が異なる
if self.hi ^ self.lo < 0 {
// オーバーフロー発生時の例外処理
}
}
// 除算
fn div(&mut self, rs: &i32, rt: &i32) {
let mut rs = *rs as i64;
for _ in 0..32 {
rs <<= 1;
// rs - ((*rt as i64) << 32: rsの上位32ビットからrtを引く
if rs - ((*rt as i64) << 32) < 0 {
// 最下位桁を0にする
rs &= !1;
} else {
rs = rs - ((*rt as i64) << 32);
// 最下位桁を1にする
rs |= 1;
}
}
// hi: rs ÷ rt
// lo: rs mod rt
self.hi = (rs >> 32) as i32;
self.lo = rs as i32;
// オーバーフロー検知
// オーバーフローの条件 → hi と lo の符号が異なる
if self.hi ^ self.lo < 0 {
// オーバーフロー発生時の例外処理
}
}
}
fn main() {
let mut register = Register {hi: 0, lo: 0};
register.mult(&2, &3);
println!("{} {}", register.hi, register.lo); // 0 6
register.div(&7, &2);
println!("{} {}", register.hi, register.lo); // 1 3
}