zasm: add support for .org directive
This commit is contained in:
parent
49be50b730
commit
acddb045a5
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
6
tools/tests/zasm/test8.asm
Normal file
6
tools/tests/zasm/test8.asm
Normal file
@ -0,0 +1,6 @@
|
||||
; test .org directive
|
||||
.equ foo 1234
|
||||
.org foo
|
||||
label1:
|
||||
jp label1
|
||||
jr label1
|
Loading…
Reference in New Issue
Block a user