mirror of
https://github.com/mre/mos6502.git
synced 2024-12-01 11:51:51 +00:00
Add assembly example code
This should make it easier for beginners to understand how to test this emulator.
This commit is contained in:
parent
4266599bb2
commit
8d506773bf
51
README.md
51
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.asm
|
||||||
|
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
|
## Credits
|
||||||
|
|
||||||
This started off as a fork of [amw-zero/6502-rs](https://github.com/amw-zero/6502-rs),
|
This started off as a fork of [amw-zero/6502-rs](https://github.com/amw-zero/6502-rs),
|
||||||
|
33
examples/asm/euclid/euclid.a65
Normal file
33
examples/asm/euclid/euclid.a65
Normal file
@ -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
|
BIN
examples/asm/euclid/euclid.bin
Normal file
BIN
examples/asm/euclid/euclid.bin
Normal file
Binary file not shown.
11
examples/asm/linker.cfg
Normal file
11
examples/asm/linker.cfg
Normal file
@ -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;
|
||||||
|
}
|
36
examples/euclid.rs
Normal file
36
examples/euclid.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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::<u8>().unwrap())
|
||||||
|
.collect::<Vec<u8>>();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
// print all files in the current directory
|
||||||
|
println!("Files in current directory:");
|
||||||
|
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);
|
||||||
|
}
|
@ -5,7 +5,7 @@ use mos6502::memory::Bus;
|
|||||||
use mos6502::memory::Memory;
|
use mos6502::memory::Memory;
|
||||||
|
|
||||||
fn main() {
|
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();
|
let mut input = String::new();
|
||||||
std::io::stdin().read_line(&mut input).unwrap();
|
std::io::stdin().read_line(&mut input).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user