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

zasm: allow .org to be specified from command line

Also important for upcoming mega commit...
This commit is contained in:
Virgil Dupras 2019-11-15 09:57:53 -05:00
parent e5255d22f9
commit d74b85f146
7 changed files with 83 additions and 16 deletions

View File

@ -3,6 +3,21 @@
This is probably the most critical part of the Collapse OS project because it This is probably the most critical part of the Collapse OS project because it
ensures its self-reproduction. ensures its self-reproduction.
## Invocation
`zasm` is invoked with 2 mandatory arguments and an optional one. The mandatory
arguments are input blockdev id and output blockdev id. For example, `zasm 0 1`
reads source code from blockdev 0, assembles it and spit the result in blockdev
1.
Input blockdev needs to be seek-able, output blockdev doesn't need to (zasm
writes in one pass, sequentially.
The 3rd argument, optional, is the initial `.org` value. It's the high byte of
the value. For example, `zasm 0 1 4f` assembles source in blockdev 0 as if it
started with the line `.org 0x4f00`. This also means that the initial value of
the `@` symbol is `0x4f00`.
## Running on a "modern" machine ## Running on a "modern" machine
To be able to develop zasm efficiently, [libz80][libz80] is used to run zasm To be able to develop zasm efficiently, [libz80][libz80] is used to run zasm

View File

@ -8,14 +8,17 @@
; whether we're in "local pass", that is, in local label scanning mode. During ; whether we're in "local pass", that is, in local label scanning mode. During
; this special pass, ZASM_FIRST_PASS will also be set so that the rest of the ; this special pass, ZASM_FIRST_PASS will also be set so that the rest of the
; code behaves as is we were in the first pass. ; code behaves as is we were in the first pass.
.equ ZASM_LOCAL_PASS ZASM_FIRST_PASS+1 .equ ZASM_LOCAL_PASS @+1
; What IO_PC was when we started our context ; What IO_PC was when we started our context
.equ ZASM_CTX_PC ZASM_LOCAL_PASS+1 .equ ZASM_CTX_PC @+1
; current ".org" offset, that is, what we must offset all our label by. ; current ".org" offset, that is, what we must offset all our label by.
.equ ZASM_ORG ZASM_CTX_PC+2 .equ ZASM_ORG @+2
.equ ZASM_RAMEND ZASM_ORG+2 .equ ZASM_RAMEND @+2
; Takes 2 byte arguments, blkdev in and blkdev out, expressed as IDs. ; Takes 2 byte arguments, blkdev in and blkdev out, expressed as IDs.
; Can optionally take a 3rd argument which is the high byte of the initial
; .org. For example, passing 0x42 to this 3rd arg is the equivalent of beginning
; the unit with ".org 0x4200".
; Read file through blkdev in and outputs its upcodes through blkdev out. ; Read file through blkdev in and outputs its upcodes through blkdev out.
; HL is set to the last lineno to be read. ; HL is set to the last lineno to be read.
; Sets Z on success, unset on error. On error, A contains an error code (ERR_*) ; Sets Z on success, unset on error. On error, A contains an error code (ERR_*)
@ -23,7 +26,7 @@ zasmMain:
; Parse args. HL points to string already ; Parse args. HL points to string already
; We don't allocate memory just to hold this. Because this happens ; We don't allocate memory just to hold this. Because this happens
; before initialization, we don't really care where those args are ; before initialization, we don't really care where those args are
; parsed. ; parsed. That's why we borrow zasm's RAMSTART for a little while.
ld de, .argspecs ld de, .argspecs
ld ix, ZASM_RAMSTART ld ix, ZASM_RAMSTART
call parseArgs call parseArgs
@ -44,11 +47,18 @@ zasmMain:
ld de, IO_OUT_BLK ld de, IO_OUT_BLK
call blkSel call blkSel
; Init modules ; Init .org
; This is the 3rd argument, optional, will be zero if not given.
; Save in "@" too
ld a, (ZASM_RAMSTART+2)
ld (ZASM_ORG+1), a ; high byte of .org
ld (DIREC_LASTVAL+1), a
xor a xor a
ld (ZASM_ORG), a ; low byte zero in all cases
ld (DIREC_LASTVAL), a
; And then the rest.
ld (ZASM_LOCAL_PASS), a ld (ZASM_LOCAL_PASS), a
ld (ZASM_ORG), a
ld (ZASM_ORG+1), a
call ioInit call ioInit
call symInit call symInit
@ -73,7 +83,7 @@ zasmMain:
jp ioLineNo ; --> HL, --> DE, returns jp ioLineNo ; --> HL, --> DE, returns
.argspecs: .argspecs:
.db 0b001, 0b001, 0 .db 0b001, 0b001, 0b101
.sFirstPass: .sFirstPass:
.db "First pass", 0 .db "First pass", 0
.sSecondPass: .sSecondPass:

View File

@ -56,13 +56,20 @@ init:
ld de, BLOCKDEV_SEL ld de, BLOCKDEV_SEL
call blkSel call blkSel
call fsOn call fsOn
; There's a special understanding between zasm.c and this unit: The
; addresses 0xff00 and 0xff01 contain the two ascii chars to send to
; zasm as the 3rd argument.
ld a, (0xff00)
ld (.zasmArgs+4), a
ld a, (0xff01)
ld (.zasmArgs+5), a
ld hl, .zasmArgs ld hl, .zasmArgs
call USER_CODE call USER_CODE
; signal the emulator we're done ; signal the emulator we're done
halt halt
.zasmArgs: .zasmArgs:
.db "0 1", 0 .db "0 1 XX", 0
; *** I/O *** ; *** I/O ***
emulGetB: emulGetB:

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "../libz80/z80.h" #include "../libz80/z80.h"
#include "kernel-bin.h" #include "kernel-bin.h"
#include "zasm-bin.h" #include "zasm-bin.h"
@ -8,8 +9,11 @@
* in another specified blkdev. In our emulator layer, we use stdin and stdout * in another specified blkdev. In our emulator layer, we use stdin and stdout
* as those specified blkdevs. * as those specified blkdevs.
* *
* This executable takes one argument: the path to a .cfs file to use for * This executable takes two arguments. Both are optional, but you need to
* includes. * specify the first one if you want to get to the second one.
* The first one is the value to send to z80-zasm's 3rd argument (the initial
* .org). Defaults to '00'.
* The second one is the path to a .cfs file to use for includes.
* *
* Because the input blkdev needs support for Seek, we buffer it in the emulator * Because the input blkdev needs support for Seek, we buffer it in the emulator
* layer. * layer.
@ -155,7 +159,7 @@ static void mem_write(int unused, uint16_t addr, uint8_t val)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc > 2) { if (argc > 3) {
fprintf(stderr, "Too many args\n"); fprintf(stderr, "Too many args\n");
return 1; return 1;
} }
@ -166,9 +170,19 @@ int main(int argc, char *argv[])
for (int i=0; i<sizeof(USERSPACE); i++) { for (int i=0; i<sizeof(USERSPACE); i++) {
mem[i+USER_CODE] = USERSPACE[i]; mem[i+USER_CODE] = USERSPACE[i];
} }
char *init_org = "00";
if (argc >= 2) {
init_org = argv[1];
if (strlen(init_org) != 2) {
fprintf(stderr, "Initial org must be a two-character hex string");
}
}
// glue.asm knows that it needs to fetch these arguments at this address.
mem[0xff00] = init_org[0];
mem[0xff01] = init_org[1];
fsdev_size = 0; fsdev_size = 0;
if (argc == 2) { if (argc == 3) {
FILE *fp = fopen(argv[1], "r"); FILE *fp = fopen(argv[2], "r");
if (fp == NULL) { if (fp == NULL) {
fprintf(stderr, "Can't open file %s\n", argv[1]); fprintf(stderr, "Can't open file %s\n", argv[1]);
return 1; return 1;

View File

@ -1,9 +1,30 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Calls tools/emul/zasm/zasm in a convenient manner by wrapping specified
# paths to include in a single CFS file and then pass that file to zasm.
# Additionally, it takes a "-o" argument to set the initial ".org" of the
# binary. For example, "zasm.sh -o 4f < foo.asm" assembles foo.asm as if it
# started with the line ".org 0x4f00".
# readlink -f doesn't work with macOS's implementation # readlink -f doesn't work with macOS's implementation
# so, if we can't get readlink -f to work, try python with a realpath implementation # so, if we can't get readlink -f to work, try python with a realpath implementation
ABS_PATH=$(readlink -f "$0" || python -c "import os; print(os.path.realpath('$0'))") ABS_PATH=$(readlink -f "$0" || python -c "import os; print(os.path.realpath('$0'))")
usage() { echo "Usage: $0 [-o <hexorg>] <paths-to-include>..." 1>&2; exit 1; }
org='00'
while getopts ":o:" opt; do
case "${opt}" in
o)
org=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
# wrapper around ./emul/zasm/zasm that prepares includes CFS prior to call # wrapper around ./emul/zasm/zasm that prepares includes CFS prior to call
DIR=$(dirname "${ABS_PATH}") DIR=$(dirname "${ABS_PATH}")
ZASMBIN="${DIR}/emul/zasm/zasm" ZASMBIN="${DIR}/emul/zasm/zasm"
@ -16,7 +37,7 @@ for p in "$@"; do
"${CFSPACK}" "${p}" "*.bin" >> "${INCCFS}" "${CFSPACK}" "${p}" "*.bin" >> "${INCCFS}"
done done
"${ZASMBIN}" "${INCCFS}" "${ZASMBIN}" "${org}" "${INCCFS}"
RES=$? RES=$?
rm "${INCCFS}" rm "${INCCFS}"
exit $RES exit $RES