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
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
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
; 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.
.equ ZASM_LOCAL_PASS ZASM_FIRST_PASS+1
.equ ZASM_LOCAL_PASS @+1
; 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.
.equ ZASM_ORG ZASM_CTX_PC+2
.equ ZASM_RAMEND ZASM_ORG+2
.equ ZASM_ORG @+2
.equ ZASM_RAMEND @+2
; 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.
; 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_*)
@ -23,7 +26,7 @@ zasmMain:
; Parse args. HL points to string already
; We don't allocate memory just to hold this. Because this happens
; 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 ix, ZASM_RAMSTART
call parseArgs
@ -44,11 +47,18 @@ zasmMain:
ld de, IO_OUT_BLK
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
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_ORG), a
ld (ZASM_ORG+1), a
call ioInit
call symInit
@ -73,7 +83,7 @@ zasmMain:
jp ioLineNo ; --> HL, --> DE, returns
.argspecs:
.db 0b001, 0b001, 0
.db 0b001, 0b001, 0b101
.sFirstPass:
.db "First pass", 0
.sSecondPass:

View File

@ -56,13 +56,20 @@ init:
ld de, BLOCKDEV_SEL
call blkSel
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
call USER_CODE
; signal the emulator we're done
halt
.zasmArgs:
.db "0 1", 0
.db "0 1 XX", 0
; *** I/O ***
emulGetB:

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,6 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "../libz80/z80.h"
#include "kernel-bin.h"
#include "zasm-bin.h"
@ -8,8 +9,11 @@
* in another specified blkdev. In our emulator layer, we use stdin and stdout
* as those specified blkdevs.
*
* This executable takes one argument: the path to a .cfs file to use for
* includes.
* This executable takes two arguments. Both are optional, but you need to
* 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
* layer.
@ -155,7 +159,7 @@ static void mem_write(int unused, uint16_t addr, uint8_t val)
int main(int argc, char *argv[])
{
if (argc > 2) {
if (argc > 3) {
fprintf(stderr, "Too many args\n");
return 1;
}
@ -166,9 +170,19 @@ int main(int argc, char *argv[])
for (int i=0; i<sizeof(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;
if (argc == 2) {
FILE *fp = fopen(argv[1], "r");
if (argc == 3) {
FILE *fp = fopen(argv[2], "r");
if (fp == NULL) {
fprintf(stderr, "Can't open file %s\n", argv[1]);
return 1;

View File

@ -1,9 +1,30 @@
#!/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
# 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'))")
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
DIR=$(dirname "${ABS_PATH}")
ZASMBIN="${DIR}/emul/zasm/zasm"
@ -16,7 +37,7 @@ for p in "$@"; do
"${CFSPACK}" "${p}" "*.bin" >> "${INCCFS}"
done
"${ZASMBIN}" "${INCCFS}"
"${ZASMBIN}" "${org}" "${INCCFS}"
RES=$?
rm "${INCCFS}"
exit $RES