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

View File

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

View File

@ -11,7 +11,9 @@
.equ ZASM_LOCAL_PASS ZASM_FIRST_PASS+1 .equ ZASM_LOCAL_PASS ZASM_FIRST_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 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 ; Read file through blockdev ID in H and outputs its upcodes through blockdev
; ID in L. ; ID in L.
@ -27,6 +29,8 @@ zasmMain:
; Init modules ; Init modules
xor a xor a
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
@ -54,6 +58,20 @@ zasmIsLocalPass:
cp 1 cp 1
ret 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 ; 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 ; IO. Z is set on success, unset on error. DE contains the last line number to
; be read (first line is 1). ; be read (first line is 1).
@ -135,7 +153,10 @@ _parseLabel:
call _endLocalPass call _endLocalPass
jr .success jr .success
.registerLabel: .registerLabel:
ld de, (IO_PC) push hl
call zasmGetPC
ex de, hl
pop hl
call symRegister call symRegister
jr nz, .error jr nz, .error
; continue to .success ; continue to .success

View File

@ -226,13 +226,10 @@ parseLiteral:
parseNumberOrSymbol: parseNumberOrSymbol:
call parseLiteral call parseLiteral
ret z ret z
call zasmIsFirstPass
ret z ; first pass? we don't care about the value,
; return success.
; Not a number. Try symbol ; Not a number. Try symbol
call symSelect call symSelect
call symFind call symFind
ret nz ; not found jr nz, .notfound
; Found! let's fetch value ; Found! let's fetch value
push de push de
call symGetVal call symGetVal
@ -241,3 +238,9 @@ parseNumberOrSymbol:
pop de pop de
cp a ; ensure Z cp a ; ensure Z
ret 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 ; If successful, Z is set and A is the symbol index. Otherwise, Z is unset and
; A is an error code (SYM_ERR_*). ; A is an error code (SYM_ERR_*).
symRegister: symRegister:
call symFind
jr z, .alreadyThere
push hl ; will be used during processing. it's the symbol to add push hl ; will be used during processing. it's the symbol to add
push de ; will be used during processing. it's our value. push de ; will be used during processing. it's our value.
; First, let's get our strlen ; First, let's get our strlen
call strlen call strlen
ld c, a ; save that strlen for later ld c, a ; save that strlen for later
@ -201,11 +205,20 @@ symRegister:
ret ret
.error: .error:
; Z already unset call unsetZ
pop de pop de
pop hl pop hl
ret 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) ; Select global or local registry according to label name in (HL)
symSelect: symSelect:
call symIsLabelLocal call symIsLabelLocal

View File

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