parsing registers
This commit is contained in:
parent
75d765c905
commit
9228b7949b
|
|
@ -8,5 +8,8 @@ as0.o: as0.asm
|
||||||
test: test.bin
|
test: test.bin
|
||||||
./test.bin
|
./test.bin
|
||||||
|
|
||||||
|
print_table: as0.o
|
||||||
|
ld -m elf_x86_64 -e _entry_print_table -o print_table as0.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f as0.o test.bin
|
rm -f as0.o test.bin
|
||||||
|
|
|
||||||
1423
stages/as0/as0.asm
1423
stages/as0/as0.asm
File diff suppressed because it is too large
Load diff
|
|
@ -1,49 +1,51 @@
|
||||||
unsafe extern "C" {
|
unsafe extern "C" {
|
||||||
unsafe fn parse_gpr(src: *mut Source, prefix: u8) -> (u64, u64);
|
// unsafe fn parse_gpr(src: *mut Source, prefix: u8) -> (u64, u64);
|
||||||
unsafe fn parse_reg(src: *mut Source) -> (u64, u64);
|
// unsafe fn parse_reg(src: *mut Source) -> (u64, u64);
|
||||||
|
|
||||||
|
unsafe fn try_parse_reg() -> (usize, Register);
|
||||||
|
|
||||||
|
#[link_name = "buf"]
|
||||||
|
static mut BUF: [u8; 0x100];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Source<'a> {
|
#[repr(C)]
|
||||||
iter: core::iter::Peekable<core::slice::Iter<'a, u8>>,
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
struct Register {
|
||||||
|
size: u32,
|
||||||
|
num: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a [u8]> for Source<'a> {
|
impl Register {
|
||||||
fn from(value: &'a [u8]) -> Self {
|
fn new(num: u32, size: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
iter: value.iter().peekable(),
|
num,
|
||||||
|
size: size.ilog2(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[cfg(test)]
|
||||||
extern "C" fn peekc(src: *mut Source) -> u8 {
|
mod tests {
|
||||||
unsafe { (*src).iter.peek().cloned().unwrap_or(&0).clone() }
|
use super::*;
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
fn write_to_buf(b: &[u8]) {
|
||||||
extern "C" fn getc(src: *mut Source) -> u8 {
|
assert!(b.len() <= 0x100, "Buffer overflow");
|
||||||
unsafe { (*src).iter.next().unwrap_or(&0).clone() }
|
unsafe {
|
||||||
}
|
core::ptr::copy_nonoverlapping(b.as_ptr(), (&raw mut BUF).cast(), b.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_reg() {
|
fn parse_reg() {
|
||||||
let cases = [
|
let cases = [
|
||||||
(&b"rax"[..], (0, 8)),
|
(&b"rax"[..], (0, 8)),
|
||||||
(&b"rbx"[..], (1, 8)),
|
(&b"rcx"[..], (1, 8)),
|
||||||
(&b"rcx"[..], (2, 8)),
|
(&b"rdx"[..], (2, 8)),
|
||||||
(&b"rdx"[..], (3, 8)),
|
(&b"rbx"[..], (3, 8)),
|
||||||
(&b"rsp"[..], (4, 8)),
|
(&b"rsp"[..], (4, 8)),
|
||||||
(&b"rbp"[..], (5, 8)),
|
(&b"rbp"[..], (5, 8)),
|
||||||
(&b"rsi"[..], (6, 8)),
|
(&b"rsi"[..], (6, 8)),
|
||||||
(&b"rdi"[..], (7, 8)),
|
(&b"rdi"[..], (7, 8)),
|
||||||
(&b"eax"[..], (0, 4)),
|
|
||||||
(&b"ebx"[..], (1, 4)),
|
|
||||||
(&b"ecx"[..], (2, 4)),
|
|
||||||
(&b"edx"[..], (3, 4)),
|
|
||||||
(&b"esp"[..], (4, 4)),
|
|
||||||
(&b"ebp"[..], (5, 4)),
|
|
||||||
(&b"esi"[..], (6, 4)),
|
|
||||||
(&b"edi"[..], (7, 4)),
|
|
||||||
(&b"r8"[..], (8, 8)),
|
(&b"r8"[..], (8, 8)),
|
||||||
(&b"r9"[..], (9, 8)),
|
(&b"r9"[..], (9, 8)),
|
||||||
(&b"r10"[..], (10, 8)),
|
(&b"r10"[..], (10, 8)),
|
||||||
|
|
@ -52,6 +54,15 @@ fn test_parse_reg() {
|
||||||
(&b"r13"[..], (13, 8)),
|
(&b"r13"[..], (13, 8)),
|
||||||
(&b"r14"[..], (14, 8)),
|
(&b"r14"[..], (14, 8)),
|
||||||
(&b"r15"[..], (15, 8)),
|
(&b"r15"[..], (15, 8)),
|
||||||
|
(&b"rip"[..], (!0, 8)),
|
||||||
|
(&b"eax"[..], (0, 4)),
|
||||||
|
(&b"ecx"[..], (1, 4)),
|
||||||
|
(&b"edx"[..], (2, 4)),
|
||||||
|
(&b"ebx"[..], (3, 4)),
|
||||||
|
(&b"esp"[..], (4, 4)),
|
||||||
|
(&b"ebp"[..], (5, 4)),
|
||||||
|
(&b"esi"[..], (6, 4)),
|
||||||
|
(&b"edi"[..], (7, 4)),
|
||||||
(&b"r8d"[..], (8, 4)),
|
(&b"r8d"[..], (8, 4)),
|
||||||
(&b"r9d"[..], (9, 4)),
|
(&b"r9d"[..], (9, 4)),
|
||||||
(&b"r10d"[..], (10, 4)),
|
(&b"r10d"[..], (10, 4)),
|
||||||
|
|
@ -77,139 +88,32 @@ fn test_parse_reg() {
|
||||||
(&b"r14b"[..], (14, 1)),
|
(&b"r14b"[..], (14, 1)),
|
||||||
(&b"r15b"[..], (15, 1)),
|
(&b"r15b"[..], (15, 1)),
|
||||||
(&b"ax"[..], (0, 2)),
|
(&b"ax"[..], (0, 2)),
|
||||||
(&b"bx"[..], (1, 2)),
|
(&b"cx"[..], (1, 2)),
|
||||||
(&b"cx"[..], (2, 2)),
|
(&b"dx"[..], (2, 2)),
|
||||||
(&b"dx"[..], (3, 2)),
|
(&b"bx"[..], (3, 2)),
|
||||||
(&b"sp"[..], (4, 2)),
|
(&b"sp"[..], (4, 2)),
|
||||||
(&b"bp"[..], (5, 2)),
|
(&b"bp"[..], (5, 2)),
|
||||||
(&b"si"[..], (6, 2)),
|
(&b"si"[..], (6, 2)),
|
||||||
(&b"di"[..], (7, 2)),
|
(&b"di"[..], (7, 2)),
|
||||||
(&b"al"[..], (0, 1)),
|
(&b"al"[..], (0, 1)),
|
||||||
(&b"bl"[..], (1, 1)),
|
(&b"cl"[..], (1, 1)),
|
||||||
(&b"cl"[..], (2, 1)),
|
(&b"dl"[..], (2, 1)),
|
||||||
(&b"dl"[..], (3, 1)),
|
(&b"bl"[..], (3, 1)),
|
||||||
(&b"ah"[..], (0, 3)),
|
(&b"spl"[..], (4, 1)),
|
||||||
(&b"bh"[..], (1, 3)),
|
(&b"bpl"[..], (5, 1)),
|
||||||
(&b"ch"[..], (2, 3)),
|
|
||||||
(&b"dh"[..], (3, 3)),
|
|
||||||
(&b"sil"[..], (6, 1)),
|
(&b"sil"[..], (6, 1)),
|
||||||
(&b"dil"[..], (7, 1)),
|
(&b"dil"[..], (7, 1)),
|
||||||
(&b"asd"[..], (0, 0)),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
for (text, result) in cases {
|
for (text, (reg, size)) in cases {
|
||||||
let mut src = Source::from(text);
|
write_to_buf(text);
|
||||||
unsafe {
|
let (n, result) = unsafe { try_parse_reg() };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_reg(&mut src),
|
|
||||||
result,
|
result,
|
||||||
"Failed to parse '{}'",
|
Register::new(reg, size),
|
||||||
|
"Failed to parse '{}' n={n}",
|
||||||
std::str::from_utf8(text).unwrap()
|
std::str::from_utf8(text).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_gpr() {
|
|
||||||
let cases = [
|
|
||||||
(&b"ax"[..], (0, 2)),
|
|
||||||
(&b"bx"[..], (1, 2)),
|
|
||||||
(&b"cx"[..], (2, 2)),
|
|
||||||
(&b"dx"[..], (3, 2)),
|
|
||||||
(&b"sp"[..], (4, 2)),
|
|
||||||
(&b"bp"[..], (5, 2)),
|
|
||||||
(&b"si"[..], (6, 2)),
|
|
||||||
(&b"di"[..], (7, 2)),
|
|
||||||
(&b"al"[..], (0, 1)),
|
|
||||||
(&b"bl"[..], (1, 1)),
|
|
||||||
(&b"cl"[..], (2, 1)),
|
|
||||||
(&b"dl"[..], (3, 1)),
|
|
||||||
(&b"ah"[..], (0, 3)),
|
|
||||||
(&b"bh"[..], (1, 3)),
|
|
||||||
(&b"ch"[..], (2, 3)),
|
|
||||||
(&b"dh"[..], (3, 3)),
|
|
||||||
(&b"sil"[..], (6, 1)),
|
|
||||||
(&b"dil"[..], (7, 1)),
|
|
||||||
(&b"asd"[..], (0, 0)),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (text, result) in cases {
|
|
||||||
let mut src = Source::from(text);
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
parse_gpr(&mut src, b'r'),
|
|
||||||
result,
|
|
||||||
"Failed to parse '{}'",
|
|
||||||
std::str::from_utf8(text).unwrap()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Register {
|
|
||||||
A = 0,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
D,
|
|
||||||
Src,
|
|
||||||
Dst,
|
|
||||||
Sp,
|
|
||||||
Bp,
|
|
||||||
R8,
|
|
||||||
R9,
|
|
||||||
R10,
|
|
||||||
R11,
|
|
||||||
R12,
|
|
||||||
R13,
|
|
||||||
R14,
|
|
||||||
R15,
|
|
||||||
}
|
|
||||||
enum RegisterSize {
|
|
||||||
Byte = 1,
|
|
||||||
Word = 2,
|
|
||||||
Dword = 4,
|
|
||||||
Qword = 8,
|
|
||||||
HighByte = 3,
|
|
||||||
None = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
struct PackedRegister(u8);
|
|
||||||
impl From<PackedRegister> for Option<(Register, RegisterSize)> {
|
|
||||||
fn from(value: PackedRegister) -> Self {
|
|
||||||
let reg_bits = value.0 & 0x00F;
|
|
||||||
let size_bits = (value.0 >> 4) & 0x0F;
|
|
||||||
let size = match size_bits {
|
|
||||||
1 => RegisterSize::Byte,
|
|
||||||
2 => RegisterSize::Word,
|
|
||||||
4 => RegisterSize::Dword,
|
|
||||||
8 => RegisterSize::Qword,
|
|
||||||
3 => RegisterSize::HighByte,
|
|
||||||
0 => return None,
|
|
||||||
_ => panic!("Invalid register size"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let reg = match reg_bits {
|
|
||||||
0 => Register::A,
|
|
||||||
1 => Register::B,
|
|
||||||
2 => Register::C,
|
|
||||||
3 => Register::D,
|
|
||||||
4 => Register::Sp,
|
|
||||||
5 => Register::Bp,
|
|
||||||
6 => Register::Src,
|
|
||||||
7 => Register::Dst,
|
|
||||||
8 => Register::R8,
|
|
||||||
9 => Register::R9,
|
|
||||||
10 => Register::R10,
|
|
||||||
11 => Register::R11,
|
|
||||||
12 => Register::R12,
|
|
||||||
13 => Register::R13,
|
|
||||||
14 => Register::R14,
|
|
||||||
15 => Register::R15,
|
|
||||||
_ => panic!("Invalid register number"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Some((reg, size))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue