parsing registers

This commit is contained in:
janis 2026-07-06 12:30:30 +02:00
parent 75d765c905
commit 9228b7949b
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
3 changed files with 825 additions and 917 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -1,215 +1,119 @@
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);
}
struct Source<'a> { unsafe fn try_parse_reg() -> (usize, Register);
iter: core::iter::Peekable<core::slice::Iter<'a, u8>>,
}
impl<'a> From<&'a [u8]> for Source<'a> { #[link_name = "buf"]
fn from(value: &'a [u8]) -> Self { static mut BUF: [u8; 0x100];
Self {
iter: value.iter().peekable(),
}
}
}
#[unsafe(no_mangle)]
extern "C" fn peekc(src: *mut Source) -> u8 {
unsafe { (*src).iter.peek().cloned().unwrap_or(&0).clone() }
}
#[unsafe(no_mangle)]
extern "C" fn getc(src: *mut Source) -> u8 {
unsafe { (*src).iter.next().unwrap_or(&0).clone() }
}
#[test]
fn test_parse_reg() {
let cases = [
(&b"rax"[..], (0, 8)),
(&b"rbx"[..], (1, 8)),
(&b"rcx"[..], (2, 8)),
(&b"rdx"[..], (3, 8)),
(&b"rsp"[..], (4, 8)),
(&b"rbp"[..], (5, 8)),
(&b"rsi"[..], (6, 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"r9"[..], (9, 8)),
(&b"r10"[..], (10, 8)),
(&b"r11"[..], (11, 8)),
(&b"r12"[..], (12, 8)),
(&b"r13"[..], (13, 8)),
(&b"r14"[..], (14, 8)),
(&b"r15"[..], (15, 8)),
(&b"r8d"[..], (8, 4)),
(&b"r9d"[..], (9, 4)),
(&b"r10d"[..], (10, 4)),
(&b"r11d"[..], (11, 4)),
(&b"r12d"[..], (12, 4)),
(&b"r13d"[..], (13, 4)),
(&b"r14d"[..], (14, 4)),
(&b"r15d"[..], (15, 4)),
(&b"r8w"[..], (8, 2)),
(&b"r9w"[..], (9, 2)),
(&b"r10w"[..], (10, 2)),
(&b"r11w"[..], (11, 2)),
(&b"r12w"[..], (12, 2)),
(&b"r13w"[..], (13, 2)),
(&b"r14w"[..], (14, 2)),
(&b"r15w"[..], (15, 2)),
(&b"r8b"[..], (8, 1)),
(&b"r9b"[..], (9, 1)),
(&b"r10b"[..], (10, 1)),
(&b"r11b"[..], (11, 1)),
(&b"r12b"[..], (12, 1)),
(&b"r13b"[..], (13, 1)),
(&b"r14b"[..], (14, 1)),
(&b"r15b"[..], (15, 1)),
(&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_reg(&mut src),
result,
"Failed to parse '{}'",
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)] #[repr(C)]
struct PackedRegister(u8); #[derive(Debug, PartialEq, Eq)]
impl From<PackedRegister> for Option<(Register, RegisterSize)> { struct Register {
fn from(value: PackedRegister) -> Self { size: u32,
let reg_bits = value.0 & 0x00F; num: u32,
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 { impl Register {
0 => Register::A, fn new(num: u32, size: u32) -> Self {
1 => Register::B, Self {
2 => Register::C, num,
3 => Register::D, size: size.ilog2(),
4 => Register::Sp, }
5 => Register::Bp, }
6 => Register::Src, }
7 => Register::Dst,
8 => Register::R8, #[cfg(test)]
9 => Register::R9, mod tests {
10 => Register::R10, use super::*;
11 => Register::R11,
12 => Register::R12, fn write_to_buf(b: &[u8]) {
13 => Register::R13, assert!(b.len() <= 0x100, "Buffer overflow");
14 => Register::R14, unsafe {
15 => Register::R15, core::ptr::copy_nonoverlapping(b.as_ptr(), (&raw mut BUF).cast(), b.len());
_ => panic!("Invalid register number"), }
}; }
Some((reg, size)) #[test]
fn parse_reg() {
let cases = [
(&b"rax"[..], (0, 8)),
(&b"rcx"[..], (1, 8)),
(&b"rdx"[..], (2, 8)),
(&b"rbx"[..], (3, 8)),
(&b"rsp"[..], (4, 8)),
(&b"rbp"[..], (5, 8)),
(&b"rsi"[..], (6, 8)),
(&b"rdi"[..], (7, 8)),
(&b"r8"[..], (8, 8)),
(&b"r9"[..], (9, 8)),
(&b"r10"[..], (10, 8)),
(&b"r11"[..], (11, 8)),
(&b"r12"[..], (12, 8)),
(&b"r13"[..], (13, 8)),
(&b"r14"[..], (14, 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"r9d"[..], (9, 4)),
(&b"r10d"[..], (10, 4)),
(&b"r11d"[..], (11, 4)),
(&b"r12d"[..], (12, 4)),
(&b"r13d"[..], (13, 4)),
(&b"r14d"[..], (14, 4)),
(&b"r15d"[..], (15, 4)),
(&b"r8w"[..], (8, 2)),
(&b"r9w"[..], (9, 2)),
(&b"r10w"[..], (10, 2)),
(&b"r11w"[..], (11, 2)),
(&b"r12w"[..], (12, 2)),
(&b"r13w"[..], (13, 2)),
(&b"r14w"[..], (14, 2)),
(&b"r15w"[..], (15, 2)),
(&b"r8b"[..], (8, 1)),
(&b"r9b"[..], (9, 1)),
(&b"r10b"[..], (10, 1)),
(&b"r11b"[..], (11, 1)),
(&b"r12b"[..], (12, 1)),
(&b"r13b"[..], (13, 1)),
(&b"r14b"[..], (14, 1)),
(&b"r15b"[..], (15, 1)),
(&b"ax"[..], (0, 2)),
(&b"cx"[..], (1, 2)),
(&b"dx"[..], (2, 2)),
(&b"bx"[..], (3, 2)),
(&b"sp"[..], (4, 2)),
(&b"bp"[..], (5, 2)),
(&b"si"[..], (6, 2)),
(&b"di"[..], (7, 2)),
(&b"al"[..], (0, 1)),
(&b"cl"[..], (1, 1)),
(&b"dl"[..], (2, 1)),
(&b"bl"[..], (3, 1)),
(&b"spl"[..], (4, 1)),
(&b"bpl"[..], (5, 1)),
(&b"sil"[..], (6, 1)),
(&b"dil"[..], (7, 1)),
];
for (text, (reg, size)) in cases {
write_to_buf(text);
let (n, result) = unsafe { try_parse_reg() };
assert_eq!(
result,
Register::new(reg, size),
"Failed to parse '{}' n={n}",
std::str::from_utf8(text).unwrap()
);
}
} }
} }