Closed tomoyuki-nakabayashi closed 6 years ago
一旦仮で、↓みたいにしてみよう。
#[test]
fn load() {
let bin = load("binary");
assert_eq!(bin.get(), 0x00b80000);
}
Rustでfile open。 https://doc.rust-lang.org/std/fs/struct.File.html
use std::fs::File;
use std::io::prelude::*;
fn main() -> std::io::Result<()> {
let mut file = File::open("foo.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
assert_eq!(contents, "Hello, world!");
Ok(())
}
preludeとは? Rust のプレリュード (prelude) とは何か
あー、Result<BinaryHandler, Error>みたいな感じにして返せば良いのか。
これは参考になる。
x86命令セットひどいな…。デコード方法が全然わからん。
命令を、mov bx, 0
にすると、b8からbbになる。ふむ?
$ hexdump mov
0000000 00bb 0000
https://wiki.osdev.org/X86-64_Instruction_Encoding
地道にこのあたりを見ていくか。
↓は重要やね。
Opcode
The opcode can be 1, 2 or 3 bytes in length. Depending on the opcode escape sequence, a different opcode map is selected. Possible opcode sequences are:
<op>
0x0F <op>
0x0F 0x38 <op>
0x0F 0x3A <op>
cxだと0xb9、dxだと0xba
どういうことや?
A⇒C⇒D⇒Bの順番か。一応意味ある単語の頭文字だから…。これで納得いった。
The 8 GPRs are:
1. Accumulator register (AX). Used in arithmetic operations
2. Counter register (CX). Used in shift/rotate instructions and loops.
3. Data register (DX). Used in arithmetic operations and I/O operations.
4. Base register (BX). Used as a pointer to data (located in segment register DS, when in segmented mode).
5. Stack Pointer register (SP). Pointer to the top of the stack.
6. Stack Base Pointer register (BP). Used to point to the base of the stack.
7. Source Index register (SI). Used as a pointer to a source in stream operations.
8. Destination Index register (DI). Used as a pointer to a destination in stream operations.
これでバイト列比較できるのええな。
let mov_rax: &[u8] = &[0xb8, 0x00, 0x00, 0x00, 0x00, 0x00];
assert_eq!(mov_rax, buffer);
で、Rustでコマンドライン引数やるには?
getoptsを使ってみる。
https://github.com/rust-lang-nursery/getopts http://ubnt-intrepid.hatenablog.com/entry/rust_commandline_parsers
簡単にできるじゃないの。
$ cargo run
Usage: target/debug/rustemu86 FILE [options]
Options:
-b NAME Set input binary name
-h, --help Print this help menu
cargo runするときは--
がオプションのセパレータになる。ほほー。
rustemu86 BINARY_FILE [options]
としたいので、freeから1つ引数を取ることにした。
pub(crate) fn parse_args() -> Args {
let args: Vec<String> = env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.optflag("h", "help", "Print this help menu");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m }
Err(f) => { panic!(f.to_string()) }
};
if matches.opt_present("h") {
print_usage(&program, &opts);
}
if matches.free.is_empty() {
print_usage(&program, &opts)
}
Args {
file_path: matches.free[0].clone(),
}
}
うーん、ローダーってどうあるべきなんだろうか? ロードして、バイナリにアクセスする構造を返すべきだよね。