1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 06:28:06 +11:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Virgil Dupras
1b01f13105 lib/expr: refactor for easier operator addition 2019-11-22 14:45:12 -05:00
Virgil Dupras
fd5b2ab856 Put app-common documentation in apps/README.md 2019-11-22 14:01:16 -05:00
12 changed files with 140 additions and 77 deletions

View File

@ -61,3 +61,38 @@ relevant parts of the app's glue unit in your kernel's glue unit. This is often
simpler and more efficient. However, if your shell is a big program, it might simpler and more efficient. However, if your shell is a big program, it might
run into zasm's limits. In that case, you'd have to assemble your shell run into zasm's limits. In that case, you'd have to assemble your shell
separately. separately.
## Common features
The folder `lib/` contains code shared in more than one apps and this has the
effect that some concepts are exactly the same in many application. They are
therefore sharing documentation, here.
### Number literals
There are decimal, hexadecimal and binary literals. A "straight" number is
parsed as a decimal. Hexadecimal literals must be prefixed with `0x` (`0xf4`).
Binary must be prefixed with `0b` (`0b01100110`).
Decimals and hexadecimal are "flexible". Whether they're written in a byte or
a word, you don't need to prefix them with zeroes. Watch out for overflow,
however.
Binary literals are also "flexible" (`0b110` is fine), but can't go over a byte.
There is also the char literal (`'X'`), that is, two quotes with a character in
the middle. The value of that character is interpreted as-is, without any
encoding involved. That is, whatever binary code is written in between those
two quotes, it's what is evaluated. Only a single byte at once can be evaluated
thus. There is no escaping. `'''` results in `0x27`. You can't express a newline
this way, it's going to mess with the parser.
### Expressions
An expression is a bunch of literals or symbols assembled by operators. For
now, only `+`, `-` and `*` operators are supported. No parenthesis yet.
Symbols have a different meaning depending on the application. In zasm, it's
labels and constants. In basic, it's variables.
Expressions can't contain spaces.

View File

@ -49,12 +49,11 @@ by typing a whitespace.
Only 16-bit integers (unsigned for now) are supported in this BASIC. When Only 16-bit integers (unsigned for now) are supported in this BASIC. When
printed, they're printed in decimal form. When expressing number literals, you printed, they're printed in decimal form. When expressing number literals, you
can do so either in decimal (`42`), hexadecimal (`0x2a`), binary (`0b101010`) can do so either in multiple forms. . See "Number literals" in `apps/README.md`
or char ('a', resulting in number 97). for details.
Expressions are accepted wherever a number is expected. For example, Expressions are accepted wherever a number is expected. For example,
`print 2+3` will print `5`. Expressions can't have whitespace inside them and `print 2+3` will print `5`. See "Expressions" in `apps/README.md`.
don't support (yet) parentheses. Supported operators are `+`, `-`, `*` and `/`.
Inside a `if` command, "truth" expressions are accepted (`=`, `<`, `>`, `<=`, Inside a `if` command, "truth" expressions are accepted (`=`, `<`, `>`, `<=`,
`>=`). A thruth expression that doesn't contain a truth operator evaluates the `>=`). A thruth expression that doesn't contain a truth operator evaluates the

View File

@ -25,3 +25,20 @@ divide:
sbc a, d sbc a, d
ld h, a ld h, a
ret ret
; DE * BC -> DE (high) and HL (low)
multDEBC:
ld hl, 0
ld a, 0x10
.loop:
add hl, hl
rl e
rl d
jr nc, .noinc
add hl, bc
jr nc, .noinc
inc de
.noinc:
dec a
jr nz, .loop
ret

View File

@ -23,16 +23,30 @@ parseExpr:
ret ret
_parseExpr: _parseExpr:
ld a, '+' ld de, exprTbl
.loop:
ld a, (de)
or a
jp z, EXPR_PARSE ; no operator, just parse the literal
push de ; --> lvl 1. save operator row
call _findAndSplit call _findAndSplit
jp z, _applyPlus jr z, .found
ld a, '-' pop de ; <-- lvl 1
call _findAndSplit inc de \ inc de \ inc de
jp z, _applyMinus jr .loop
ld a, '*' .found:
call _findAndSplit ; Operator found, string splitted. Left in (HL), right in (DE)
jp z, _applyMult call _resolveLeftAndRight
jp EXPR_PARSE ; Whether _resolveLeftAndRight was a success, we pop our lvl 1 stack
; out, which contains our operator row. We pop it in HL because we
; don't need our string anymore. L-R numbers are parsed, and in DE and
; IX.
pop hl ; <-- lvl 1
ret nz
; Resolving left and right succeeded, proceed!
inc hl ; point to routine pointer
call intoHL
jp (hl)
; Given a string in (HL) and a separator char in A, return a splitted string, ; Given a string in (HL) and a separator char in A, return a splitted string,
; that is, the same (HL) string but with the found A char replaced by a null ; that is, the same (HL) string but with the found A char replaced by a null
@ -88,20 +102,25 @@ _resolveLeftAndRight:
pop de ; numeric left expr result in DE pop de ; numeric left expr result in DE
jp parseExpr jp parseExpr
; Parse expr in (HL) and expr in (DE) and apply + operator to both sides. ; Routines in here all have the same signature: they take two numbers, DE (left)
; Put result in IX. ; and IX (right), apply the operator and put the resulting number in IX.
_applyPlus: ; The table has 3 bytes per row: 1 byte for operator and 2 bytes for routine
call _resolveLeftAndRight ; pointer.
ret nz exprTbl:
; Good! let's do the math! IX has our right part, DE has our left one. .db '+'
.dw .plus
.db '-'
.dw .minus
.db '*'
.dw .mult
.db 0 ; end of table
.plus:
add ix, de add ix, de
cp a ; ensure Z cp a ; ensure Z
ret ret
; Same as _applyPlus but with - .minus:
_applyMinus:
call _resolveLeftAndRight
ret nz
push ix push ix
pop hl pop hl
ex de, hl ex de, hl
@ -112,9 +131,7 @@ _applyMinus:
cp a ; ensure Z cp a ; ensure Z
ret ret
_applyMult: .mult:
call _resolveLeftAndRight
ret nz
push ix \ pop bc push ix \ pop bc
call multDEBC call multDEBC
push hl \ pop ix push hl \ pop ix

View File

@ -73,20 +73,3 @@ strlen:
pop hl pop hl
pop bc pop bc
ret ret
; DE * BC -> DE (high) and HL (low)
multDEBC:
ld hl, 0
ld a, 0x10
.loop:
add hl, hl
rl e
rl d
jr nc, .noinc
add hl, bc
jr nc, .noinc
inc de
.noinc:
dec a
jr nz, .loop
ret

View File

@ -28,28 +28,13 @@ The resulting `zasm` binary takes asm code in stdin and spits binary in stdout.
## Literals ## Literals
There are decimal, hexadecimal and binary literals. A "straight" number is See "Number literals" in `apps/README.md`.
parsed as a decimal. Hexadecimal literals must be prefixed with `0x` (`0xf4`).
Binary must be prefixed with `0b` (`0b01100110`).
Decimals and hexadecimal are "flexible". Whether they're written in a byte or On top of common literal logic, zasm also has string literals. It's a chain of
a word, you don't need to prefix them with zeroes. Watch out for overflow, characters surrounded by double quotes. Example: `"foo"`. This literal can only
however. be used in the `.db` directive and is equivalent to each character being
single-quoted and separated by commas (`'f', 'o', 'o'`). No null char is
Binary literals are also "flexible" (`0b110` is fine), but can't go over a byte. inserted in the resulting value (unlike what C does).
There is also the char literal (`'X'`), that is, two qutes with a character in
the middle. The value of that character is interpreted as-is, without any
encoding involved. That is, whatever binary code is written in between those
two quotes, it's what is evaluated. Only a single byte at once can be evaluated
thus. There is no escaping. `'''` results in `0x27`. You can't express a newline
this way, it's going to mess with the parser.
Then comes our last literal, the string literal. It's a chain of characters
surrounded by double quotes. Example: `"foo"`. This literal can only be used
in the `.db` directive and is equivalent to each character being single-quoted
and separated by commas (`'f', 'o', 'o'`). No null char is inserted in the
resulting value (unlike what C does).
## Labels ## Labels
@ -100,11 +85,7 @@ of declaration order.
## Expressions ## Expressions
Wherever a constant is expected, an expression can be written. An expression See "Expressions" in `apps/README.md`.
is a bunch of literals or symbols assembled by operators. For now, only `+`, `-`
and `*` operators are supported. No parenthesis yet.
Expressions can't contain spaces.
## The Program Counter ## The Program Counter

View File

@ -66,6 +66,7 @@ jp zasmMain
.inc "core.asm" .inc "core.asm"
.inc "zasm/const.asm" .inc "zasm/const.asm"
.inc "lib/util.asm" .inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "lib/parse.asm" .inc "lib/parse.asm"
.inc "lib/args.asm" .inc "lib/args.asm"
.inc "zasm/util.asm" .inc "zasm/util.asm"

View File

@ -3,6 +3,7 @@ jp test
.inc "core.asm" .inc "core.asm"
.inc "str.asm" .inc "str.asm"
.inc "lib/util.asm" .inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "lib/parse.asm" .inc "lib/parse.asm"
.equ EXPR_PARSE parseLiteral .equ EXPR_PARSE parseLiteral
.inc "lib/expr.asm" .inc "lib/expr.asm"

View File

@ -12,6 +12,7 @@ jp test
.inc "core.asm" .inc "core.asm"
.inc "str.asm" .inc "str.asm"
.inc "lib/util.asm" .inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "zasm/util.asm" .inc "zasm/util.asm"
.inc "zasm/const.asm" .inc "zasm/const.asm"
.inc "lib/parse.asm" .inc "lib/parse.asm"

View File

@ -0,0 +1,35 @@
jp test
.inc "core.asm"
.inc "lib/ari.asm"
testNum: .db 1
test:
ld sp, 0xffff
ld de, 12
ld bc, 4
call multDEBC
ld a, l
cp 48
jp nz, fail
call nexttest
; success
xor a
halt
nexttest:
ld a, (testNum)
inc a
ld (testNum), a
ret
fail:
ld a, (testNum)
halt

View File

@ -12,14 +12,6 @@ test:
ld hl, 0xffff ld hl, 0xffff
ld sp, hl ld sp, hl
ld de, 12
ld bc, 4
call multDEBC
ld a, l
cp 48
jp nz, fail
call nexttest
ld hl, sFoo ld hl, sFoo
call strlen call strlen
cp 3 cp 3

View File

@ -4,6 +4,7 @@ jp runTests
.inc "core.asm" .inc "core.asm"
.inc "str.asm" .inc "str.asm"
.inc "zasm/const.asm" .inc "zasm/const.asm"
.inc "lib/ari.asm"
.inc "lib/util.asm" .inc "lib/util.asm"
.inc "zasm/util.asm" .inc "zasm/util.asm"
.inc "lib/parse.asm" .inc "lib/parse.asm"