zasm: add support for .org directive

This commit is contained in:
Virgil Dupras 2019-05-19 13:22:14 -04:00
parent 49be50b730
commit acddb045a5
6 changed files with 67 additions and 21 deletions

View File

@ -3,7 +3,8 @@
.equ D_DB 0x00
.equ D_DW 0x01
.equ D_EQU 0x02
.equ D_INC 0x03
.equ D_ORG 0x03
.equ D_INC 0x04
.equ D_BAD 0xff
; *** Variables ***
@ -16,6 +17,7 @@ directiveNames:
.db ".DB", 0
.db ".DW", 0
.db ".EQU"
.db ".ORG"
.db "#inc"
; This is a list of handlers corresponding to indexes in directiveNames
@ -23,6 +25,7 @@ directiveHandlers:
.dw handleDB
.dw handleDW
.dw handleEQU
.dw handleORG
.dw handleINC
handleDB:
@ -67,14 +70,6 @@ handleDW:
ret
handleEQU:
call zasmIsFirstPass
jr nz, .begin
; first pass? .equ are noops Consume args and return
call readWord
call readWord
xor a
ret
.begin:
push hl
push de
push bc
@ -90,12 +85,10 @@ handleEQU:
call readWord
ld hl, scratchpad
call parseExpr
jr nz, .error
jr nz, .end
ld hl, DIREC_SCRATCHPAD
push ix \ pop de
call symRegister
jr .end
.error:
.end:
xor a ; 0 bytes written
pop bc
@ -103,6 +96,13 @@ handleEQU:
pop hl
ret
handleORG:
call readWord
call parseExpr
ret nz
push ix \ pop hl
jp zasmSetOrg
handleINC:
call readWord
jr nz, .end

View File

@ -675,7 +675,7 @@ getUpcode:
bit 7, (ix+3)
jr z, .absoluteValue ; bit not set? regular byte value,
; Our argument is a relative address ("e" type in djnz and jr). We have
; to subtract (IO_PC) from it.
; to subtract PC from it.
; First, check whether we're on first pass. If we are, skip processing
; below because not having real symbol value makes relative address
@ -686,7 +686,10 @@ getUpcode:
; We're on second pass
push de ; Don't let go of this, that's our dest
ld de, (IO_PC)
push hl
call zasmGetPC ; --> HL
ex de, hl
pop hl
call intoHL
dec hl ; what we write is "e-2"
dec hl

View File

@ -11,7 +11,9 @@
.equ ZASM_LOCAL_PASS ZASM_FIRST_PASS+1
; What IO_PC was when we started our context
.equ ZASM_CTX_PC ZASM_LOCAL_PASS+1
.equ ZASM_RAMEND ZASM_CTX_PC+2
; 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
; Read file through blockdev ID in H and outputs its upcodes through blockdev
; ID in L.
@ -27,6 +29,8 @@ zasmMain:
; Init modules
xor a
ld (ZASM_LOCAL_PASS), a
ld (ZASM_ORG), a
ld (ZASM_ORG+1), a
call ioInit
call symInit
@ -54,6 +58,20 @@ zasmIsLocalPass:
cp 1
ret
; Set ZASM_ORG to specified number in HL
zasmSetOrg:
ld (ZASM_ORG), hl
ret
; Return current PC (properly .org offsetted) in HL
zasmGetPC:
push de
ld hl, (ZASM_ORG)
ld de, (IO_PC)
add hl, de
pop de
ret
; Repeatedly reads lines from IO, assemble them and spit the binary code in
; IO. Z is set on success, unset on error. DE contains the last line number to
; be read (first line is 1).
@ -135,7 +153,10 @@ _parseLabel:
call _endLocalPass
jr .success
.registerLabel:
ld de, (IO_PC)
push hl
call zasmGetPC
ex de, hl
pop hl
call symRegister
jr nz, .error
; continue to .success

View File

@ -226,13 +226,10 @@ parseLiteral:
parseNumberOrSymbol:
call parseLiteral
ret z
call zasmIsFirstPass
ret z ; first pass? we don't care about the value,
; return success.
; Not a number. Try symbol
call symSelect
call symFind
ret nz ; not found
jr nz, .notfound
; Found! let's fetch value
push de
call symGetVal
@ -241,3 +238,9 @@ parseNumberOrSymbol:
pop de
cp a ; ensure Z
ret
.notfound:
; If not found, check if we're in first pass. If we are, it doesn't
; matter that we didn't find our symbol. Return success anyhow.
; Otherwise return error. Z is already unset, so in fact, this is the
; same as jumping to zasmIsFirstPass
jp zasmIsFirstPass

View File

@ -155,9 +155,13 @@ symNamesEnd:
; If successful, Z is set and A is the symbol index. Otherwise, Z is unset and
; A is an error code (SYM_ERR_*).
symRegister:
call symFind
jr z, .alreadyThere
push hl ; will be used during processing. it's the symbol to add
push de ; will be used during processing. it's our value.
; First, let's get our strlen
call strlen
ld c, a ; save that strlen for later
@ -201,11 +205,20 @@ symRegister:
ret
.error:
; Z already unset
call unsetZ
pop de
pop hl
ret
.alreadyThere:
push hl
ld hl, (SYM_CTX_PTR)
ex de, hl
call writeHLinDE
pop hl
cp a ; ensure Z
ret
; Select global or local registry according to label name in (HL)
symSelect:
call symIsLabelLocal

View File

@ -0,0 +1,6 @@
; test .org directive
.equ foo 1234
.org foo
label1:
jp label1
jr label1