Improve user guide
This commit is contained in:
parent
9aae4ea040
commit
f571664853
@ -7,4 +7,4 @@ properly running.
|
||||
## Table of Contents
|
||||
|
||||
* [The shell](shell.md)
|
||||
|
||||
* [Load code in RAM and run it](load-run-code.md)
|
||||
|
110
doc/load-run-code.md
Normal file
110
doc/load-run-code.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Load code in RAM and run it
|
||||
|
||||
Collapse OS likely runs from ROM code. If you need to fiddle with your machine
|
||||
more deeply, you will want to send arbitrary code to it and run it. You can do
|
||||
so with the shell's `load` and `call` commands.
|
||||
|
||||
For example, let's say that you want to run this simple code that you have
|
||||
sitting on your "modern" machine and want to execute on your running Collapse OS
|
||||
machine:
|
||||
|
||||
ld a, (0xa100)
|
||||
inc a
|
||||
ld (0xa100), a
|
||||
ret
|
||||
|
||||
(we must always return at the end of code that we call with `call`). This will
|
||||
increase a number at memory address `0xa100`. First, compile it:
|
||||
|
||||
scas -o tosend.bin tosend.asm
|
||||
|
||||
Now, we'll send that code to address `0xa000`:
|
||||
|
||||
> seek a000
|
||||
A000
|
||||
> load 8 (resulting binary is 8 bytes long)
|
||||
|
||||
Now, at this point, it's a bit delicate. To pipe your binary to your serial
|
||||
connection, you have to close `screen` with CTRL+A then `:quit` to free your
|
||||
tty device. Then, you can run:
|
||||
|
||||
cat tosend.bin > /dev/ttyUSB0 (or whatever is your device)
|
||||
|
||||
You can then re-open your connection with screen. You'll have a blank screen,
|
||||
but if the number of characters sent corresponds to what you gave `load`, then
|
||||
Collapse OS will be waiting for a new command. Go ahead, verify that the
|
||||
transfer was successful with:
|
||||
|
||||
peek 8
|
||||
3A00A13C3200A1C9
|
||||
|
||||
Good! Now, we can try to run it. Before we run it, let's peek at the value at
|
||||
`0xa100` (being RAM, it's random):
|
||||
|
||||
> seek a100
|
||||
A100
|
||||
> peek
|
||||
61
|
||||
|
||||
So, we'll expect this to become `62` after we run the code. Let's go:
|
||||
|
||||
> seek a000
|
||||
A000
|
||||
> call 00 0000
|
||||
> seek a100
|
||||
A100
|
||||
> peek
|
||||
62
|
||||
|
||||
Success!
|
||||
|
||||
## Labels in RAM code
|
||||
|
||||
If your code contains any label, make sure that you add a `.org` directive at
|
||||
the beginning of your code with the address you're planning on uploading your
|
||||
code to. Otherwise, those labels are going to point to wrong addresses.
|
||||
|
||||
## Calling ROM code
|
||||
|
||||
The ROM you run Collapse OS on already has quite a bit of code in it, some of
|
||||
it could be useful to programs you run from RAM.
|
||||
|
||||
If you know exactly where a routine lives in the ROM, you can `call` the address
|
||||
directly, no problem. However, getting this information is tedious work and is
|
||||
likely to change whenever you change the kernel code.
|
||||
|
||||
A good approach is to define yourself a jump table that you put in your glue
|
||||
code. A good place for this is in the `0x03` to `0x37` range, which is empty
|
||||
anyways (unless you set yourself up with some `rst` jumps) and is needed to
|
||||
have a proper interrupt hook at `0x38`. For example, your glue code could look
|
||||
like (important fact: `jp <addr>` uses 3 bytes):
|
||||
|
||||
jp init
|
||||
; JUMP TABLE
|
||||
jp printstr
|
||||
jp aciaPutC
|
||||
|
||||
.fill 0x38-$
|
||||
jp aciaInt
|
||||
|
||||
init:
|
||||
[...]
|
||||
|
||||
It then becomes easy to build yourself a predictable and stable jump header,
|
||||
something you could call `jumptable.inc`:
|
||||
|
||||
JUMP_PRINTSTR .equ 0x03
|
||||
JUMP_ACIAPUTC .equ 0x06
|
||||
|
||||
You can then include that file in your "user" code, like this:
|
||||
|
||||
#include "jumptable.inc"
|
||||
.org 0xa000
|
||||
ld hl, label
|
||||
call JUMP_PRINTSTR
|
||||
ret
|
||||
|
||||
label: .db "Hello World!", 0
|
||||
|
||||
If you load that code at `0xa000` and call it, it will print "Hello World!" by
|
||||
using the `printstr` routine from `core.asm`.
|
Loading…
Reference in New Issue
Block a user