ft: initial disasm of example data
This only contains two instructions of which I know the correct output.
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
403
Cargo.lock
generated
Normal file
403
Cargo.lock
generated
Normal file
@@ -0,0 +1,403 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"once_cell",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc95de49ad098572c02d3fbf368c9a020bfff5ae78483685b77f51d8a7e9486d"
|
||||||
|
dependencies = [
|
||||||
|
"num_threads",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_filter"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.11.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"env_filter",
|
||||||
|
"jiff",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-static",
|
||||||
|
"log",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-static"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.172"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mimix-8086-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"env",
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_threads"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.95"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.219"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.219"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "mimix-8086-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.5.37", features = ["derive"] }
|
||||||
|
env = "1.0.1"
|
||||||
|
env_logger = "0.11.8"
|
||||||
|
log = "0.4.27"
|
||||||
62
src/aout.rs
Normal file
62
src/aout.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use std::ffi::{c_uchar, c_ushort};
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub type c_long = i32; // we use a a.out with 32 byte
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Aout {
|
||||||
|
pub header: Header,
|
||||||
|
pub text: Vec<u8>,
|
||||||
|
pub data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Aout {
|
||||||
|
pub fn new(buf: Vec<u8>) -> Self {
|
||||||
|
let hdr = Header {
|
||||||
|
magic: [buf[0], buf[1]],
|
||||||
|
flags: buf[2],
|
||||||
|
cpu: buf[3],
|
||||||
|
hdrlen: buf[4],
|
||||||
|
unused: buf[5],
|
||||||
|
version: c_ushort::from_be_bytes([buf[6], buf[7]]),
|
||||||
|
text: c_long::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]),
|
||||||
|
data: c_long::from_le_bytes([buf[12], buf[13], buf[14], buf[15]]),
|
||||||
|
bss: c_long::from_le_bytes([buf[16], buf[17], buf[18], buf[19]]),
|
||||||
|
entry: c_long::from_le_bytes([buf[20], buf[21], buf[22], buf[23]]),
|
||||||
|
total: c_long::from_le_bytes([buf[24], buf[25], buf[26], buf[27]]),
|
||||||
|
syms: c_long::from_le_bytes([buf[28], buf[29], buf[30], buf[31]]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let text_start = hdr.hdrlen as usize;
|
||||||
|
let text_end = text_start + hdr.text as usize;
|
||||||
|
let data_start = text_end + 1;
|
||||||
|
let data_end = data_start + hdr.data as usize;
|
||||||
|
|
||||||
|
let text_section = &buf[text_start..text_end];
|
||||||
|
let data_section = &buf[data_start..data_end];
|
||||||
|
|
||||||
|
Aout {
|
||||||
|
header: hdr,
|
||||||
|
text: Vec::from(text_section),
|
||||||
|
data: Vec::from(data_section),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Header {
|
||||||
|
pub magic: [c_uchar; 2], // magic number
|
||||||
|
pub flags: c_uchar, // flags, see below
|
||||||
|
pub cpu: c_uchar, // cpu id
|
||||||
|
pub hdrlen: c_uchar, // length of header
|
||||||
|
pub unused: c_uchar, // reserved for future use
|
||||||
|
pub version: c_ushort, // version stamp
|
||||||
|
pub text: c_long, // size of text segment in bytes
|
||||||
|
pub data: c_long, // size of data segment in bytes
|
||||||
|
pub bss: c_long, // size of bss segment in bytes
|
||||||
|
pub entry: c_long, // entry point
|
||||||
|
pub total: c_long, // total memory allocated
|
||||||
|
pub syms: c_long, // size of symbol table
|
||||||
|
}
|
||||||
1
src/decode.rs
Normal file
1
src/decode.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
103
src/disasm.rs
Normal file
103
src/disasm.rs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use std::{fs::File, io::Read, process::exit};
|
||||||
|
|
||||||
|
use crate::aout::Aout;
|
||||||
|
use crate::{
|
||||||
|
Args,
|
||||||
|
instructions::{ImmediateByte, ImmediateWord, Instruction, MetaInstruction, Register},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DisasmError {
|
||||||
|
NoFile(Option<String>),
|
||||||
|
IoError(std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for DisasmError {
|
||||||
|
fn from(error: std::io::Error) -> Self {
|
||||||
|
DisasmError::IoError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DisasmError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
DisasmError::NoFile(msg) => write!(f, "No file error: {:?}", msg),
|
||||||
|
DisasmError::IoError(msg) => write!(f, "{}", msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disassemble the binary in `path` into a vector of instructions
|
||||||
|
/// This function just calls all other
|
||||||
|
pub fn disasm(args: &Args) -> Result<Vec<MetaInstruction>, DisasmError> {
|
||||||
|
let contents = path_to_buf(args)?;
|
||||||
|
let aout = Aout::new(contents);
|
||||||
|
|
||||||
|
// XXX: 00 is just 0, maybe this could be a problem?
|
||||||
|
log::debug!("{:?}", aout);
|
||||||
|
|
||||||
|
let instructions = decode_instructions(&aout)?;
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a filepath into a buffer
|
||||||
|
fn path_to_buf(args: &Args) -> Result<Vec<u8>, DisasmError> {
|
||||||
|
let path = args
|
||||||
|
.path
|
||||||
|
.clone()
|
||||||
|
.ok_or(DisasmError::NoFile(args.path.clone()))?;
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
file.read_to_end(&mut buf)?;
|
||||||
|
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decode instructions from the text section of the provided binary
|
||||||
|
fn decode_instructions(aout: &Aout) -> Result<Vec<MetaInstruction>, DisasmError> {
|
||||||
|
// naive approach:
|
||||||
|
// 1. read byte
|
||||||
|
// 2. pattern match to see which instruction it is
|
||||||
|
// 3. read as many bytes as this instruction needs (registers, immidiates, ...)
|
||||||
|
// repeat until no bytes left
|
||||||
|
|
||||||
|
let instructions = Vec::new();
|
||||||
|
let mut offset = 0;
|
||||||
|
|
||||||
|
let text = &aout.text;
|
||||||
|
while offset < aout.text.len() {
|
||||||
|
let mut instr = MetaInstruction::new();
|
||||||
|
instr.start = offset;
|
||||||
|
|
||||||
|
let opcode = text[offset];
|
||||||
|
match opcode {
|
||||||
|
// 0x00 => {} // ADD
|
||||||
|
// INT
|
||||||
|
0xCD => {
|
||||||
|
instr.take_n_bytes(2, &mut offset, text);
|
||||||
|
instr.instruction = Instruction::INT(ImmediateByte(instr.raw[1]));
|
||||||
|
}
|
||||||
|
// MOV
|
||||||
|
0xBB => {
|
||||||
|
instr.take_n_bytes(3, &mut offset, text);
|
||||||
|
instr.instruction = Instruction::MOV_RI(
|
||||||
|
Register::BX,
|
||||||
|
ImmediateWord(u16::from_le_bytes([instr.raw[1], instr.raw[2]])),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("Encountered unknown instruction '0x{:x}'", opcode);
|
||||||
|
eprintln!("Offset might be misaligned and data is being interpreted.");
|
||||||
|
eprintln!("Existing to avoid further misinterpretation...");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{}", instr);
|
||||||
|
// dbg!(&instr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
183
src/instructions.rs
Normal file
183
src/instructions.rs
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
pub type MemAddress = u8;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
/// A single 'line' of executable ASM is called a MetaInstruction, which
|
||||||
|
/// contains the `Instruction`, which will be executed, alongside some Meta
|
||||||
|
/// Informations.
|
||||||
|
pub struct MetaInstruction {
|
||||||
|
pub start: usize, // location of the instruction start
|
||||||
|
pub size: usize, // size of the instruction in bytes
|
||||||
|
pub raw: Vec<u8>, // raw value of instruction
|
||||||
|
pub instruction: Instruction, // actual instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MetaInstruction {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
MetaInstruction {
|
||||||
|
start: 0,
|
||||||
|
size: 0,
|
||||||
|
raw: Vec::new(),
|
||||||
|
instruction: Instruction::NOP(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse n bytes from text section and advance offet.
|
||||||
|
/// Used to get the operands.
|
||||||
|
pub fn take_n_bytes(&mut self, size: usize, offset: &mut usize, text: &Vec<u8>) {
|
||||||
|
self.size = size;
|
||||||
|
self.raw = text[*offset as usize..]
|
||||||
|
.iter()
|
||||||
|
.take(size)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
*offset += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MetaInstruction {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{:04x}: ", self.start).unwrap();
|
||||||
|
for b in self.raw.iter() {
|
||||||
|
write!(f, "{:02x}", b).unwrap();
|
||||||
|
}
|
||||||
|
write!(f, "\t{}", self.instruction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code, non_camel_case_types)]
|
||||||
|
pub enum Instruction {
|
||||||
|
NOP(),
|
||||||
|
// ADD
|
||||||
|
ADD_RM(Register, Memory),
|
||||||
|
ADD_MR(Memory, Register),
|
||||||
|
ADD_RR(Register, Register),
|
||||||
|
ADD_MI(Memory, ImmediateByte),
|
||||||
|
ADD_RI(Register, ImmediateByte),
|
||||||
|
// MOV
|
||||||
|
MOV_RM(Register, Memory),
|
||||||
|
MOV_MR(Memory, Register),
|
||||||
|
MOV_RR(Register, Register),
|
||||||
|
MOV_MI(Memory, ImmediateByte),
|
||||||
|
MOV_RI(Register, ImmediateWord),
|
||||||
|
MOV_SM(SRegister, Memory),
|
||||||
|
MOV_MS(Memory, SRegister),
|
||||||
|
MOV_RS(Register, SRegister),
|
||||||
|
MOV_SR(SRegister, Register),
|
||||||
|
// INT
|
||||||
|
INT(ImmediateByte),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Instruction {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::INT(byte) => write!(f, "INT, {:x}", byte),
|
||||||
|
Self::MOV_RI(reg, word) => write!(f, "MOV {}, {:04x}", reg, word),
|
||||||
|
_ => write!(f, "display not yet implemented"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types for operand encoding
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Memory(pub MemAddress);
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ImmediateByte(pub u8);
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ImmediateWord(pub u16);
|
||||||
|
|
||||||
|
// ... and the displays for all of them
|
||||||
|
impl fmt::Display for Memory {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for ImmediateByte {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::LowerHex for ImmediateByte {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::LowerHex::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for ImmediateWord {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::LowerHex for ImmediateWord {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::LowerHex::fmt(&self.0, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers of a 8086 processor
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum Register {
|
||||||
|
AX,
|
||||||
|
BX,
|
||||||
|
CX,
|
||||||
|
DX,
|
||||||
|
AH,
|
||||||
|
AL,
|
||||||
|
BL,
|
||||||
|
BH,
|
||||||
|
CH,
|
||||||
|
CL,
|
||||||
|
DH,
|
||||||
|
DL,
|
||||||
|
DI,
|
||||||
|
SI,
|
||||||
|
BP,
|
||||||
|
SP,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Register {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::AX => write!(f, "AX"),
|
||||||
|
Self::BX => write!(f, "BX"),
|
||||||
|
Self::CX => write!(f, "CX"),
|
||||||
|
Self::DX => write!(f, "DX"),
|
||||||
|
Self::AH => write!(f, "AH"),
|
||||||
|
Self::AL => write!(f, "AL"),
|
||||||
|
Self::BL => write!(f, "BL"),
|
||||||
|
Self::BH => write!(f, "BH"),
|
||||||
|
Self::CH => write!(f, "CH"),
|
||||||
|
Self::CL => write!(f, "CL"),
|
||||||
|
Self::DH => write!(f, "DH"),
|
||||||
|
Self::DL => write!(f, "DL"),
|
||||||
|
Self::DI => write!(f, "DI"),
|
||||||
|
Self::SI => write!(f, "SI"),
|
||||||
|
Self::BP => write!(f, "BP"),
|
||||||
|
Self::SP => write!(f, "SP"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SRegisters of a 8086 processor
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum SRegister {
|
||||||
|
DS,
|
||||||
|
ES,
|
||||||
|
SS,
|
||||||
|
CS,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SRegister {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::DS => write!(f, "DS"),
|
||||||
|
Self::ES => write!(f, "ES"),
|
||||||
|
Self::SS => write!(f, "SS"),
|
||||||
|
Self::CS => write!(f, "CS"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main.rs
Normal file
41
src/main.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
|
mod aout;
|
||||||
|
mod decode;
|
||||||
|
mod disasm;
|
||||||
|
mod instructions;
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
enum Command {
|
||||||
|
/// Disassemble the binary into 8086 instructions
|
||||||
|
Disasm,
|
||||||
|
|
||||||
|
/// Interpret the binary as 8086 Minix
|
||||||
|
Interpret,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simple prgram to diasm and interpret Minix binaries
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Command,
|
||||||
|
|
||||||
|
/// Path of the binary
|
||||||
|
#[arg(short, long, global = true)]
|
||||||
|
path: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
let args = Args::parse();
|
||||||
|
log::debug!("{:?}", args);
|
||||||
|
|
||||||
|
match args.command {
|
||||||
|
Command::Disasm => {
|
||||||
|
let _instructions = disasm::disasm(&args).unwrap();
|
||||||
|
}
|
||||||
|
_ => panic!("Command not yet implemented"),
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user