Kaynağa Gözat

doc: refer to the new BASIC shell in example

ref #80
pull/85/head
Virgil Dupras 4 yıl önce
ebeveyn
işleme
1710c865dc
7 değiştirilmiş dosya ile 112 ekleme ve 130 silme
  1. +1
    -1
      apps/basic/README.md
  2. +1
    -2
      doc/README.md
  3. +22
    -62
      doc/blockdev.md
  4. +18
    -8
      doc/fs.md
  5. +39
    -14
      doc/glue-code.md
  6. +27
    -39
      doc/load-run-code.md
  7. +4
    -4
      doc/zasm.md

+ 1
- 1
apps/basic/README.md Dosyayı Görüntüle

@@ -198,7 +198,7 @@ second.

A freshly selected blkdev begins with its "pointer" at 0.

`seek <lsw> <msw>`: Moves the blkdev "pointer" to the specified offset. The
`bseek <lsw> <msw>`: Moves the blkdev "pointer" to the specified offset. The
first argument is the offset's least significant half (blkdev supports 32-bit
addressing). Is is interpreted as an unsigned integer.



+ 1
- 2
doc/README.md Dosyayı Görüntüle

@@ -7,8 +7,7 @@

## User guide

* [The shell](../apps/shell/README.md)
* [The BASIC shell](../apps/basic/README.md)
* [The shell](../apps/basic/README.md)
* [Load code in RAM and run it](load-run-code.md)
* [Using block devices](blockdev.md)
* [Using the filesystem](fs.md)


+ 22
- 62
doc/blockdev.md Dosyayı Görüntüle

@@ -42,71 +42,31 @@ they should try to adhere to the convention, that is:
## Shell usage

`blockdev.asm` supplies 4 shell commands that you can graft to your shell thus:

[...]
SHELL_EXTRA_CMD_COUNT .equ 4
#include "shell.asm"
; extra commands
.dw blkBselCmd, blkSeekCmd, blkLoadCmd, blkSaveCmd
[...]

### bsel

`bsel` select the active block device. This specify a target for `load` and
`save`. Some applications also use the active blockdev. It receives one
argument, the device index. `bsel 0` selects the first defined device, `bsel 1`,
the second, etc. Error `0x04` when argument is out of bounds.

### seek

`seek` receives one word argument and sets the pointer for the currently active
device to the specified address. Example: `seek 1234`.

The device position is device-specific: if you seek on a device, then switch
to another device and seek again, your previous position isn't lost. You will
still be on the same position when you come back.

### load

`load` works a bit like `poke` except that it reads its data from the currently
active blockdev at its current position. If it hits the end of the blockdev
before it could load its specified number of bytes, it stops. It only raises an
error if it couldn't load any byte.

It moves the device's position to the byte after the last loaded byte.

### save

`save` is the opposite of `load`. It writes the specified number of bytes from
memory to the active blockdev at its current position.

It moves the device's position to the byte after the last written byte.
`apps/basic/blk.asm` supplies 4 shell commands that you can add to your shell.
See "Optional Modules/blk" in [the shell doc](../apps/basic/README.md).

### Example

Let's try an example: You glue yourself a Collapse OS with ACIA as its first
device and a mmap starting at `0xd000` as your second device. Here's what you
Let's try an example: You glue yourself a Collapse OS with a mmap starting at
`0xe000` as your 4th device (like it is in the shell emulator). Here's what you
could do to copy memory around:

> mptr d000
D000
> poke 4
> m=0xe000
> 10 getc
> 20 poke m a
> 30 m=m+1
> 40 if m<0xe004 goto 10
> run
[enter "abcd"]
> peek 4
61626364
> mptr c000
C000
> peek 4
[RAM garbage]
> bsel 1
> load 4
[returns immediately]
> peek 4
61626364
> seek 00 0002
> load 2
> peek 4
63646364

Awesome, right?
> bsel 3
> clear
> 10 getb
> 20 puth a
> run
61> run
62> run
63> run
64> bseek 2
> run
63> run
64>

+ 18
- 8
doc/fs.md Dosyayı Görüntüle

@@ -18,7 +18,7 @@ files, Collapse OS tries to reuse blocks from deleted files if it can.

Once "mounted" (turned on with `fson`), you can list files, allocate new files
with `fnew`, mark files as deleted with `fdel` and, more importantly, open files
with `fopn`.
with `fopen`.

Opened files are accessed a independent block devices. It's the glue code that
decides how many file handles we'll support and to which block device ID each
@@ -26,7 +26,7 @@ file handle will be assigned.

For example, you could have a system with three block devices, one for ACIA and
one for a SD card and one for a file handle. You would mount the filesystem on
block device `1` (the SD card), then open a file on handle `0` with `fopn 0
block device `1` (the SD card), then open a file on handle `0` with `fopen 0
filename`. You would then do `bsel 2` to select your third block device which
is mapped to the file you've just opened.

@@ -55,13 +55,23 @@ so it's ready to use:
> fls
foo
bar
> mptr 9000
9000
> fopn 0 foo
> fopen 0 foo
> bsel 2
> load 5
> peek 5
656C6C6F21
> getb
> puth a
65
> getb
> puth a
6C
> getb
> puth a
6C
> getb
> puth a
6F
> getb
> puth a
21
> fdel bar
> fls
foo


+ 39
- 14
doc/glue-code.md Dosyayı Görüntüle

@@ -31,25 +31,46 @@ look like:
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"

.equ SHELL_RAMSTART STDIO_RAMEND
.equ SHELL_EXTRA_CMD_COUNT 0
.inc "shell.asm"
; *** BASIC ***

; RAM space used in different routines for short term processing.
.equ SCRATCHPAD_SIZE 0x20
.equ SCRATCHPAD STDIO_RAMEND
.inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "lib/parse.asm"
.inc "lib/fmt.asm"
.equ EXPR_PARSE parseLiteralOrVar
.inc "lib/expr.asm"
.inc "basic/util.asm"
.inc "basic/parse.asm"
.inc "basic/tok.asm"
.equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE
.inc "basic/var.asm"
.equ BUF_RAMSTART VAR_RAMEND
.inc "basic/buf.asm"
.equ BAS_RAMSTART BUF_RAMEND
.inc "basic/main.asm"

init:
di
; setup stack
ld hl, RAMEND
ld sp, hl
ld sp, RAMEND
im 1

call aciaInit
call shellInit
call basInit
ei
jp shellLoop
jp basStart

Once this is written, building it is easy:
Once this is written, you can build it with `zasm`, which takes code from stdin
and spits binary to stdout. Because out code has includes, however, you need
to supply zasm with a block device containing a CFS containing the files to
include. This sounds, compicated, but it's managed by the `tools/zasm.sh` shell
script. The invocation would look like (it builds a CFS with the contents of
both `kernel/` and `apps/` folders):

zasm < glue.asm > collapseos.bin
tools/zasm.sh kernel/ apps/ < glue.asm > collapseos.bin

## Building zasm

@@ -122,19 +143,23 @@ label at the very end of its source file. This way, it becomes easy for the
glue code to "graft" entries to the table. This approach, although simple and
effective, only works for one table per part. But it's often enough.

For example, to define extra commands in the shell:
For example, to define block devices:

[...]
.equ SHELL_EXTRA_CMD_COUNT 2
#include "shell.asm"
.dw myCmd1, myCmd2
.equ BLOCKDEV_COUNT 4
.inc "blockdev.asm"
; List of devices
.dw fsdevGetB, fsdevPutB
.dw stdoutGetB, stdoutPutB
.dw stdinGetB, stdinPutB
.dw mmapGetB, mmapPutB
[...]

### Initialization

Then, finally, comes the `init` code. This can be pretty much anything really
and this much depends on the part you select. But if you want a shell, you will
usually end it with `shellLoop`, which never returns.
usually end it with `basStart`, which never returns.

[rc2014]: https://rc2014.co.uk/
[zasm]: ../tools/emul/README.md


+ 27
- 39
doc/load-run-code.md Dosyayı Görüntüle

@@ -2,7 +2,7 @@

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 `poke` and `call` commands.
so with the shell's `poke` and `usr` 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
@@ -13,16 +13,18 @@ machine:
ld (0xa100), a
ret

(we must always return at the end of code that we call with `call`). This will
(we must always return at the end of code that we call with `usr`). This will
increase a number at memory address `0xa100`. First, compile it:

zasm < tosend.asm > tosend.bin

Now, we'll send that code to address `0xa000`:

> mptr a000
A000
> poke 8 (resulting binary is 8 bytes long)
> m=0xa000
> 10 getc
> 20 poke m a
> 30 if m<0xa008 goto 10
(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
@@ -35,46 +37,45 @@ but if the number of characters sent corresponds to what you gave `poke`, then
Collapse OS will be waiting for a new command. Go ahead, verify that the
transfer was successful with:

peek 8
3A00A13C3200A1C9
> peek 0a000
> puth a
3A
> peek 0a007
> puth a
C9

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):

> mptr a100
A100
> peek
> peek 0xa100
> puth a
61

So, we'll expect this to become `62` after we run the code. Let's go:

> mptr a000
A000
> call 00 0000
> mptr a100
A100
> peek
> usr 0xa100
> peek 0xa100
> puth a
62

Success!

## The upload.py tool
## The upload tool

The serial connection is not always 100% reliable and a bad byte can slip in
when you push your code and that's not fun when you try to debug your code (is
this bad behavior caused by my logic or by a bad serial upload?). Moreover,
sending contents bigger than `0xff` bytes can be a hassle.
sending contents manually can be a hassle.

To this end, there is a `upload.py` file in `tools/` that takes care of loading
the file and verify the contents. So, instead of doing `mptr a000` followed by
`poke 8` followed by your `cat` above, you would have done:
To this end, there is a `upload` file in `tools/` (run `make` to build it) that
takes care of loading the file and verify the contents. So, instead of doing
`getc` followed by `poke` followed by your `cat` above, you would have done:

./upload.py /dev/ttyUSB0 a000 tosend.bin
./upload /dev/ttyUSB0 a000 tosend.bin

This emits `mptr`, `poke` and `peek` commands and fail appropriately if the
`peek` doesn't match sent contents. If the file is larger than `0xff` bytes,
repeat the process until the whole file was sent (file must fit in memory space
though, of course). Very handy.
This clears your basic listing and then types in a basic algorithm to receive
and echo and pre-defined number of bytes. The `upload` tool then sends and read
each byte, verifying that they're the same. Very handy.

## Labels in RAM code

@@ -126,16 +127,3 @@ You can then include that file in your "user" code, like this:

If you load that code at `0xa000` and call it, it will print "Hello World!" by
using the `printstr` routine from `core.asm`.

## Doing the same with the BASIC shell

The BASIC shell also has the capacity to load code from serial console but its
semantic is a bit different from the regular shell. Instead of peeking and
poking, you use `getc` to send data and then `putc` to send the same data back
for verification. Then, you can use `poke` to commit it to memory.

There's an upload tool that use these commands and it's `uploadb.py`. It is
invoked with the same arguments as `upload.py`.

Once your code is uploaded, you will call it with BASIC's `usr` command. See
BASIC's README for more details.

+ 4
- 4
doc/zasm.md Dosyayı Görüntüle

@@ -13,13 +13,13 @@ on a real machine, you'll have to make sure to provide these requirements.
The emulated shell has a `hello.asm` file in its mounted filesystem that is
ready to compile. It has two file handles 0 and 1, mapped to blk IDs 1 and 2.
We will open our source file in handle 0 and our dest file in handle 1. Then,
with the power of the `pgm` module, we'll autoload our newly compiled file and
execute it!
with the power of the `fs` module's autoloader, we'll load our newly compiled
file and execute it!

Collapse OS
> fnew 1 dest ; create destination file
> fopn 0 hello.asm ; open source file in handle 0
> fopn 1 dest ; open dest binary in handle 1
> fopen 0 hello.asm ; open source file in handle 0
> fopen 1 dest ; open dest binary in handle 1
> zasm 1 2 ; assemble source file into binary file
> dest ; call newly compiled file
Assembled from the shell


Yükleniyor…
İptal
Kaydet