mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 12:58:09 +11:00
Improve user guide
This commit is contained in:
parent
9aae4ea040
commit
f571664853
@ -7,4 +7,4 @@ properly running.
|
|||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
* [The shell](shell.md)
|
* [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