Files
8086-rs/src/aout.rs
Marco Thomas a5cffa4852 fix(interpreter): impl fetch and decode
I parsed all instructions before executing, but this is not how
intel works.
We need to decode the instructions, pointed to by IP, on the fly.
2025-07-01 12:08:28 +09:00

127 lines
3.6 KiB
Rust

//! Internal a.out File abstraction.
use core::fmt;
use std::{
ffi::{c_uchar, c_ushort},
fs::File,
io::Read,
};
use crate::{Args, disasm::DisasmError, operands::Byte};
#[allow(non_camel_case_types)]
pub type c_long = i32; // we use a a.out with 32 byte
#[derive(Debug, Clone)]
/// Internal representation of the a.out binary format.
pub struct Aout {
pub header: Header,
pub text: Vec<Byte>,
pub data: Vec<Byte>,
}
impl fmt::Display for Aout {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Header: {:#?}\n", self.header).unwrap();
write!(f, "Text: {:#?}\n", self.text).unwrap();
write!(f, "Data: {:#?}\n", self.data)
}
}
impl Aout {
pub fn new_from_args(args: &Args) -> Self {
let path = args
.path
.clone()
.ok_or(DisasmError::NoFile(args.path.clone()))
.unwrap();
let mut file = File::open(path).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
let aout = Aout::new(buf);
log::debug!("{:?}", aout);
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;
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, Clone)]
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
}
impl fmt::Display for Header {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Header:
Magic: {:02X?}
Flags: {:#04X}
CPU: {}
Header Length: {}
Unused: {}
Version: {:#06X}
Text Size: {}
Data Size: {}
BSS Size: {}
Entry Point: {:#X}
Total Allocated: {}
Symbol Table Size: {}
",
self.magic,
self.flags,
self.cpu,
self.hdrlen,
self.unused,
self.version,
self.text,
self.data,
self.bss,
self.entry,
self.total,
self.syms
)
}
}