Skip to content

Commit

Permalink
inc: start implement
Browse files Browse the repository at this point in the history
inc has 1/2/3/4-byte forms.
So it should be a good starting point to make a assembler.

And I added indirect mode operand to parser.

next thing: make unit-tests for indirect operand
  • Loading branch information
Gioh Kim committed Nov 20, 2024
1 parent c5e9860 commit f3c0e90
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/assembly.pest
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ COMMENT = _{ ";" ~ (!NEWLINE ~ ANY)* }

program = { SOI ~ (instruction ~ (NEWLINE | COMMENT)*)* ~ EOI }

instruction = _{ mov | add | sub | mul | div | jmp | cmp | label | org }
instruction = _{ mov | add | sub | mul | div | jmp | cmp | label | org | inc }
mov = { "mov" ~ operand ~ "," ~ operand }
add = { "add" ~ operand ~ "," ~ operand }
sub = { "sub" ~ operand ~ "," ~ operand }
Expand All @@ -13,10 +13,11 @@ div = { "div" ~ operand }
jmp = { "jmp" ~ name }
cmp = { "cmp" ~ operand ~ "," ~ operand }
org = { "org" ~ imm }
inc = { "inc" ~ operand }

name = { ASCII_ALPHANUMERIC+ }
label = { ASCII_ALPHANUMERIC+ ~ ":" }
operand = _{ register | imm | mem }
operand = _{ register | imm | mem | indirect }

/// Operand should be parsed into reg8/reg16/imm.
/// So register and number are defined as the silent rule.
Expand All @@ -34,4 +35,8 @@ mem8 = { "byte ptr" ~ memx }
mem16 = { "word ptr" ~ memx | memx }
memx = @{ "[" ~ imm ~ "]" }

indirect = { "[" ~ base* ~ index* ~ "]" }
base = { "bx" | "bp" }
index = { "si" | "di" }

hex = @{ ASCII_DIGIT | "a" | "b" | "c" | "d" | "e" | "f" }
72 changes: 72 additions & 0 deletions src/inc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use crate::memory::Memory;
use crate::parser::{imm_to_num, Rule};
use crate::{cpucontext::CpuContext, define_handler_one};
use paste::paste;
use pest::iterators::Pair;

/*
inc
1. 1-byte form: inc 16-bit registers
Opcode bit 7-3: 01000
bit 2-0: register table
2. 2-byte form: inc 8-bit registers (If operand is 8-bit reg, mod is always 11 and bit 5-3 is 000)
1-byte Opcode bit 7-1: opcode 1111111
1-byte W-bit 0: 0-operand is 8-bit
2-byte mod-bit 7-6: 11
2-byte Opcode bit 5-3: 000
2-byte bit 2-0: register table
3. 3-byte form: inc memory location
1-byte Opcode bit 7-1: 1111111
1-byte W bit 0: 0-8bit, 1-16bit
2-byte mod-bit 7-6: 01-8bit contents of next byte of instruction sign extended to 16 bits
2-byte Opcode 5-3: 000
2-byte r/m 2-0: (base and index register)
3-byte Displacement 7-0
3. 4-byte form: inc memory location
1-byte Opcode bit 7-1: 1111111
1-byte W bit 0: 0-8bit, 1-16bit
2-byte mod-bit 7-6
* 10-indirect addressing mode, use base register and 16bit displacement of next two byte of instruction
(next byte->least significant eight bits, byte after that->most sig bits)
* 00-direct addressing mode, no use base register, only use 16bit displacement
2-byte Opcode 5-3: 000
2-byte r/m 2-0: (base and index register)
3-byte Displacement 7-0
4-byte Displacement 15-8
register table
000 AX AL
001 CX CL
010 DX DL
011 BX BL
100 SP AH
101 BP CH
110 SI DH
111 DI BH
r/m field | Base register | Index Register
000 | BX | SI
001 | BX | DI
010 | BP | SI
011 | BP | DI
100 | none | SI
101 | none | DI
110 | BP | none
111 | BX | none
*/

//fn assemble_inc()

define_handler_one!(inc, first, cpu, memory, {
match first.as_rule() {
Rule::reg16 => {
let v = cpu.get_register(first.as_str()).unwrap();
cpu.set_register(first.as_str(), v + 1).unwrap();
}
_ => println!("Not supported operand for org:{:?}", first),
}
});
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod add;
mod common;
mod cpucontext;
mod inc;
mod memory;
mod mov;
mod org;
Expand Down Expand Up @@ -48,6 +49,9 @@ impl Hardware8086 {
parser::Rule::add => {
caller_two!(add, self.cpu, self.memory, instruction);
}
parser::Rule::inc => {
caller_one!(inc, self.cpu, self.memory, instruction);
}
_ => println!("NOT implemented yet:{}", line),
}
println!("After instruction: {:?}", self.cpu);
Expand Down
9 changes: 9 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,4 +267,13 @@ mod tests {

assert_eq!(Err("Invalid hex number".to_owned()), _imm_to_num("0xghi"));
}

#[test]
fn test_parser_indirect_addressing() {
// todo: add test for indirect addressing mode
// inc [bx + si]
// inc [bp + di]
// inc [si]
// ind [di]
}
}

0 comments on commit f3c0e90

Please sign in to comment.