diff --git a/README.md b/README.md index 0f7f207..fc3570b 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,57 @@ fn main() { } ``` +The same can be achieved, by compiling the euclid example yourself. + +First install a 6502 assembler and linker, e.g. [cc65](https://cc65.github.io/cc65/). + +```sh +brew install cc65 +``` + +Then compile and link the assembly file: + +```sh +cd examples/asm/euclid +ca65 euclid.a65 +ld65 -C ../linker.cfg -o euclid.bin euclid.o +``` + +This will create a binary file `euclid.bin` that you can load into the emulator: + +```rust +use mos6502::memory::Bus; +use mos6502::memory::Memory; +use mos6502::cpu; +use std::fs::read; + +fn main() { + // Calculate the greatest common divisor of 56 and 49 + // using Euclid's algorithm. + let zero_page_data = [56, 49]; + + // Load the binary file from disk + let program = match read("examples/asm/euclid/euclid.bin") { + Ok(data) => data, + Err(err) => { + println!("Error reading euclid.bin: {}", err); + return; + } + }; + + let mut cpu = cpu::CPU::new(Memory::new()); + + cpu.memory.set_bytes(0x00, &zero_page_data); + cpu.memory.set_bytes(0x10, &program); + cpu.registers.program_counter = 0x10; + + cpu.run(); + + // The expected GCD is 7 + assert_eq!(7, cpu.registers.accumulator); +} +``` + ## Credits This started off as a fork of [amw-zero/6502-rs](https://github.com/amw-zero/6502-rs), diff --git a/examples/asm/euclid/euclid.a65 b/examples/asm/euclid/euclid.a65 new file mode 100644 index 0000000..150847c --- /dev/null +++ b/examples/asm/euclid/euclid.a65 @@ -0,0 +1,33 @@ +; euclid.a65 +; A program to find the greatest common divisor of two numbers + +.ORG $1000 + +; .algo +LDA $00 ; Load from F to A +; .algo_ +sec ; Set carry flag +SBC $01 ; Subtract S from the number in A (from F) +BEQ end ; Jump to .end if the difference is zero +BMI swap ; Jump to .swap if the difference is negative +STA $00 ; Load A to F +JMP algo_ ; Jump to .algo_ + +; .end +end: +LDA $00 ; Load from F to A +BRK ; Break (end program) + +; .swap +swap: +LDX $00 ; Load F to X +LDY $01 ; Load S to Y +STX $01 ; Store X to S +STY $00 ; Store Y to F +JMP algo ; Jump to .algo + +algo: +JMP algo ; Infinite loop to prevent program from ending + +algo_: +JMP algo_ ; Infinite loop to prevent program from ending diff --git a/examples/asm/euclid/euclid.bin b/examples/asm/euclid/euclid.bin new file mode 100644 index 0000000..0c95702 Binary files /dev/null and b/examples/asm/euclid/euclid.bin differ diff --git a/examples/asm/linker.cfg b/examples/asm/linker.cfg new file mode 100644 index 0000000..0a82281 --- /dev/null +++ b/examples/asm/linker.cfg @@ -0,0 +1,11 @@ +MEMORY { + ZP: start = $0000, size = $0100, type = rw, define = yes; + RAM: start = $0100, size = $0200, type = rw, define = yes; + ROM: start = $8000, size = $8000, type = ro; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + DATA: load = RAM, type = rw; + CODE: load = ROM, type = ro; +} diff --git a/examples/euclid.rs b/examples/euclid.rs new file mode 100644 index 0000000..5636deb --- /dev/null +++ b/examples/euclid.rs @@ -0,0 +1,34 @@ +use mos6502::cpu; +use mos6502::memory::Bus; +use mos6502::memory::Memory; +use std::fs::read; + +fn main() { + println!("Enter two numbers (< 128) separated by a space to know their GCD."); + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + + let zero_page_data = input + .split_whitespace() + .map(|s| s.parse::().unwrap()) + .collect::>(); + + // Load the binary file from disk + let program = match read("examples/asm/euclid/euclid.bin") { + Ok(data) => data, + Err(err) => { + println!("Error reading euclid.bin: {}", err); + return; + } + }; + + let mut cpu = cpu::CPU::new(Memory::new()); + + cpu.memory.set_bytes(0x00, &zero_page_data); + cpu.memory.set_bytes(0x10, &program); + cpu.registers.program_counter = 0x10; + + cpu.run(); + + println!("GCD is {}", cpu.registers.accumulator); +} diff --git a/examples/euclidean_algo.rs b/examples/euclid_bytes.rs similarity index 93% rename from examples/euclidean_algo.rs rename to examples/euclid_bytes.rs index 04fc087..d261fa0 100644 --- a/examples/euclidean_algo.rs +++ b/examples/euclid_bytes.rs @@ -5,7 +5,7 @@ use mos6502::memory::Bus; use mos6502::memory::Memory; fn main() { - println!("Enter two numbers (< 128) to know their GCD:"); + println!("Enter two numbers (< 128) separated by a space to know their GCD."); let mut input = String::new(); std::io::stdin().read_line(&mut input).unwrap();