So far the INIT segment was run from the later heap+stack. Now the INIT segment is run from the later BSS. The background is that so far the INIT segment was pretty small (from $80 to $180 bytes). But upcoming changes will increase the INIT segment in certain scenarios up to ~ $1000 bytes. So programs with very limited heap+stack might just not been able to move the INIT segment to its run location. But moving the INIT segment to the later BSS allows it to occupy the later BSS+heap+stack.
In order to allow that the constructors are _NOT_ allowed anymore to access the BSS. Rather they must use the DATA segment or the new INITBSS segment. The latter isn't cleared at any point so the constructors may use it to expose values to the main program. However they must make sure to always write the values as they are not pre-initialized.
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
OVL1ADDR: load = OVL1ADDR, type = ro;
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
ZP: file = "", define = yes, start = $0002, size = $001A;
LOADADDR: file = %O, start = %S - 2, size = $0002;
HEADER: file = %O, define = yes, start = %S, size = $000D;
- RAM: file = %O, define = yes, start = __HEADER_LAST__, size = __OVERLAYSTART__ - __STACKSIZE__ - __HEADER_LAST__;
- MOVE: file = %O, start = __ZPSAVE_LOAD__, size = __HIMEM__ - __INIT_RUN__;
+ MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __OVERLAYSTART__ - __STACKSIZE__ - __HEADER_LAST__;
+ MOVE: file = %O, start = __INITBSS_LOAD__, size = __HIMEM__ - __BSS_RUN__;
+ INIT: file = "", start = __BSS_RUN__, size = __HIMEM__ - __BSS_RUN__;
OVL1ADDR: file = "%O.1", start = __OVERLAYSTART__ - 2, size = $0002;
OVL1: file = "%O.1", start = __OVERLAYSTART__, size = __OVERLAYSIZE__;
OVL2ADDR: file = "%O.2", start = __OVERLAYSTART__ - 2, size = $0002;
OVL9: file = "%O.9", start = __OVERLAYSTART__, size = __OVERLAYSIZE__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- LOADADDR: load = LOADADDR, type = ro;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes;
- OVL1ADDR: load = OVL1ADDR, type = ro;
- OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
- OVL2ADDR: load = OVL2ADDR, type = ro;
- OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
- OVL3ADDR: load = OVL3ADDR, type = ro;
- OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
- OVL4ADDR: load = OVL4ADDR, type = ro;
- OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
- OVL5ADDR: load = OVL5ADDR, type = ro;
- OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
- OVL6ADDR: load = OVL6ADDR, type = ro;
- OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
- OVL7ADDR: load = OVL7ADDR, type = ro;
- OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
- OVL8ADDR: load = OVL8ADDR, type = ro;
- OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
- OVL9ADDR: load = OVL9ADDR, type = ro;
- OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ LOADADDR: load = LOADADDR, type = ro;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INITBSS: load = MAIN, type = bss, define = yes;
+ BSS: load = MAIN, type = bss, define = yes;
+ INIT: load = MOVE, run = INIT, type = ro, define = yes;
+ OVL1ADDR: load = OVL1ADDR, type = ro;
+ OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes;
+ OVL2ADDR: load = OVL2ADDR, type = ro;
+ OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes;
+ OVL3ADDR: load = OVL3ADDR, type = ro;
+ OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes;
+ OVL4ADDR: load = OVL4ADDR, type = ro;
+ OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes;
+ OVL5ADDR: load = OVL5ADDR, type = ro;
+ OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes;
+ OVL6ADDR: load = OVL6ADDR, type = ro;
+ OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes;
+ OVL7ADDR: load = OVL7ADDR, type = ro;
+ OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes;
+ OVL8ADDR: load = OVL8ADDR, type = ro;
+ OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes;
+ OVL9ADDR: load = OVL9ADDR, type = ro;
+ OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes;
}
FEATURES {
CONDES: type = constructor,
__HIMEM__: type = weak, value = $D000;
}
MEMORY {
- ZP: file = "", define = yes, start = $0002, size = $001A;
- LOADADDR: file = %O, start = %S - 2, size = $0002;
- HEADER: file = %O, define = yes, start = %S, size = $000D;
- RAM: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __STACKSIZE__ - __HEADER_LAST__;
- MOVE: file = %O, start = __ZPSAVE_LOAD__, size = __HIMEM__ - __INIT_RUN__;
+ ZP: file = "", define = yes, start = $0002, size = $001A;
+ LOADADDR: file = %O, start = %S - 2, size = $0002;
+ HEADER: file = %O, define = yes, start = %S, size = $000D;
+ MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __STACKSIZE__ - __HEADER_LAST__;
+ MOVE: file = %O, start = __INITBSS_LOAD__, size = __HIMEM__ - __BSS_RUN__;
+ INIT: file = "", start = __BSS_RUN__, size = __HIMEM__ - __BSS_RUN__;
}
SEGMENTS {
- ZEROPAGE: load = ZP, type = zp;
- LOADADDR: load = LOADADDR, type = ro;
- EXEHDR: load = HEADER, type = ro;
- STARTUP: load = RAM, type = ro;
- LOWCODE: load = RAM, type = ro, optional = yes;
- CODE: load = RAM, type = ro;
- RODATA: load = RAM, type = ro;
- DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss, define = yes;
- BSS: load = RAM, type = bss, define = yes;
- INIT: load = MOVE, run = RAM, type = ro, define = yes;
+ ZEROPAGE: load = ZP, type = zp;
+ LOADADDR: load = LOADADDR, type = ro;
+ EXEHDR: load = HEADER, type = ro;
+ STARTUP: load = MAIN, type = ro;
+ LOWCODE: load = MAIN, type = ro, optional = yes;
+ CODE: load = MAIN, type = ro;
+ RODATA: load = MAIN, type = ro;
+ DATA: load = MAIN, type = rw;
+ INITBSS: load = MAIN, type = bss, define = yes;
+ BSS: load = MAIN, type = bss, define = yes;
+ INIT: load = MOVE, run = INIT, type = ro, define = yes;
}
FEATURES {
CONDES: type = constructor,
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = rw, define = yes;
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP, type = rw, define = yes;
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
- ZPSAVE: load = RAM, type = bss;
+ INITBSS: load = RAM, type = bss;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
}
.proc initcwd
+ lda #0
+ sta __cwd
jsr findfreeiocb
bne oserr
lda #GETCWD
; ------------------------------------------------------------------------
; Data
-.segment "ZPSAVE"
+.segment "INITBSS"
zpsave: .res zpspace
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
-
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
+ lda #0 ; The terminating NUL character
ldy FNAM_LEN
cpy #NAME_LEN + 1
bcc L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda #FNAM ; Load vector address for FETCH routine
ldx FNAM_BANK ; Load bank for FETCH routine
jsr INDFET ; Load byte from (FETVEC),y
- sta name,y ; Save byte from filename
-L1: dey
+L1: sta name,y ; Save byte from filename
+ dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem," no args.
+ beq done ; No "rem," no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
stx __argv + 1
rts
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2
-
; ------------------------------------------------------------------------
-.segment "ZPSAVE"
+.segment "INITBSS"
zpsave: .res zpspace
.include "plus4.inc"
-
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
+ lda #0 ; The terminating NUL character
ldy FNAM_LEN
cpy #NAME_LEN + 1
bcc L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda #FNAM ; Vector address
jsr FETCH ; Load byte from RAM
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem," no args.
+ beq done ; No "rem," no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
stx __argv + 1
rts
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2
-
.import initlib, donelib
.import moveinit, zerobss, callmain
.import BSOUT
- .import __RAM_START__, __RAM_SIZE__ ; Linker generated
+ .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; from configure file
.importzp ST
ldx move_init
beq L0
-; Move the INIT segment from where it was loaded (over ZPSAVE and BSS)
-; into where it must be run (in the heap).
+; Move the INIT segment from where it was loaded (over the bss segments)
+; into where it must be run (over the BSS segment).
jsr moveinit
- dec move_init ; set to false
+ dec move_init ; Set to false
-; Save space by putting the rest of the start-up code in the INIT segment,
-; which can be re-used by the heap and the C stack.
+; Save space by putting some of the start-up code in the INIT segment,
+; which can be re-used by the BSS segment, the heap and the C stack.
-L0: jsr initstart
+L0: jsr runinit
+
+; Clear the BSS data.
+
+ jsr zerobss
+
+; Push the command-line arguments; and, call main().
+
+ jsr callmain
; Back from main() [this is also the exit() entry]. Run the module destructors.
.segment "INIT"
-initstart:
+runinit:
; Save the zero-page locations that we need.
dex
bpl L1
-; Clear the BSS data.
-
- jsr zerobss
-
; Set up the stack.
- lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
- ldx #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
+ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
+ ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
sta sp
stx sp+1 ; Set argument stack ptr
; Call the module constructors.
- jsr initlib
-
-; Push the command-line arguments; and, call main().
-
- jmp callmain
+ jmp initlib
; ------------------------------------------------------------------------
move_init:
.byte 1
-.segment "ZPSAVE"
+.segment "INITBSS"
zpsave: .res zpspace
.include "c64.inc"
-
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
+ lda #0 ; The terminating NUL character
ldy FNAM_LEN
cpy #NAME_LEN + 1
bcc L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda (FNAM),y
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem," no args.
+ beq done ; No "rem," no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
stx __argv + 1
rts
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2
-
;
+ .include "cbm.inc"
.include "filedes.inc"
.code
;--------------------------------------------------------------------------
; Data
-.bss
-fdtab: .res MAX_FDS
-unittab:.res MAX_FDS
-
+.data
+fdtab: .byte LFN_READ
+ .byte LFN_WRITE
+ .byte LFN_WRITE
+ .res MAX_FDS-3
+unittab:.byte CBMDEV_KBD
+ .byte CBMDEV_SCREEN
+ .byte CBMDEV_SCREEN
+ .res MAX_FDS-3
.importzp devnum
-.bss
+.segment "INITBSS"
curunit:
.res 1
.proc initstdin
- lda #LFN_READ
- sta fdtab+STDIN_FILENO
lda #STDIN_FILENO + LFN_OFFS
ldx #CBMDEV_KBD
- stx unittab+STDIN_FILENO
ldy #$FF
jsr SETLFS
jmp OPEN ; Will always succeed
.bss
unit: .res 1
-
-
.proc initstdout
- lda #LFN_WRITE
- sta fdtab+STDOUT_FILENO
- sta fdtab+STDERR_FILENO
- lda #CBMDEV_SCREEN
- sta unittab+STDOUT_FILENO
- sta unittab+STDERR_FILENO
lda #STDOUT_FILENO + LFN_OFFS
jsr @L1
lda #STDERR_FILENO + LFN_OFFS
jmp __directerrno ; Sets _errno, clears _oserror, returns -1
.endproc
-
-
-
-
.macpack generic
-
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run.
ldy #FNAM_LEN
lda (sysp0),y
tay
+ lda #0 ; The terminating NUL character
stx IndReg ; Look for name in correct bank
cpy #NAME_LEN + 1
blt L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda (ptr1),y
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
jsr restore_bank
inc __argc ; argc always is equal to at least 1
; Find a "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- bze done ; no "rem," no args.
+ bze done ; No "rem," no args.
inx
cmp #REM
bne L2
ldy #1 * 2
; Find the next argument.
-;
+
next: lda BASIC_BUF,x
bze done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. That is useful because we
; will check now for a quoted argument; in which case, we will have to skip that
; first character.
-;
+
found: cmp #'"' ; Is the argument quoted?
beq setterm ; Jump if so
dex ; Reset pointer to first argument character
setterm:sta term ; Set end-of-argument marker
; Now, store a pointer to the argument into the next slot.
-;
+
txa ; Get low byte
add #<BASIC_BUF
sta argv,y ; argv[y]= &arg
inc __argc ; Found another arg
; Search for the end of the argument.
-;
+
argloop:lda BASIC_BUF,x
bze done
inx
; We've found the end of the argument. X points one character behind it, and
; A contains the terminating character. To make the argument a valid C string,
; replace the terminating character by a zero.
-;
+
lda #$00
sta BASIC_BUF-1,x
blt next ; Parse next one if not
; (The last vector in argv[] already is NULL.)
-;
+
done: lda #<argv
ldx #>argv
sta __argv
stx __argv + 1
rts
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
- .res MAXARGS * 2, $00
+ .res MAXARGS * 2
.macpack generic
-
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run.
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
jsr sys_bank
ldy #FNAM
lda (sysp0),y ; Get file-name pointer from system bank
ldy #FNAM_LEN
lda (sysp0),y
tay
+ lda #0 ; The terminating NUL character
stx IndReg ; Look for name in correct bank
cpy #NAME_LEN + 1
blt L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda (ptr1),y
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
jsr restore_bank
inc __argc ; argc always is equal to at least 1
; Find a "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- bze done ; no "rem," no args.
+ bze done ; No "rem," no args.
inx
cmp #REM
bne L2
ldy #1 * 2
; Find the next argument.
-;
+
next: lda BASIC_BUF,x
bze done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. That is useful because we
; will check now for a quoted argument; in which case, we will have to skip that
; first character.
-;
+
found: cmp #'"' ; Is the argument quoted?
beq setterm ; Jump if so
dex ; Reset pointer to first argument character
setterm:sta term ; Set end-of-argument marker
; Now, store a pointer to the argument into the next slot.
-;
+
txa ; Get low byte
add #<BASIC_BUF
sta argv,y ; argv[y]= &arg
inc __argc ; Found another arg
; Search for the end of the argument.
-;
+
argloop:lda BASIC_BUF,x
bze done
inx
; We've found the end of the argument. X points one character behind it, and
; A contains the terminating character. To make the argument a valid C string,
; replace the terminating character by a zero.
-;
+
lda #$00
sta BASIC_BUF-1,x
; Check if the maximum number of command-line arguments is reached. If not,
; parse the next one.
-;
+
lda __argc ; Get low byte of argument count
cmp #MAXARGS ; Maximum number of arguments reached?
blt next ; Parse next one if not
; (The last vector in argv[] already is NULL.)
-;
+
done: lda #<argv
ldx #>argv
sta __argv
stx __argv + 1
rts
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
- .res MAXARGS * 2, $00
+ .res MAXARGS * 2
.import initcwd
.include "stdio.inc"
-
+
__cwd_buf_size = FILENAME_MAX
cwd_init := initcwd
-.bss
+.segment "INITBSS"
__cwd: .res __cwd_buf_size
; checking the other sources.
.assert __cwd_buf_size < 256, error, "__cwd_buf_size must not be > 255"
-
.data
; Move the INIT segment from where it was loaded (over the bss segments)
-; into where it must be run (in the heap). The two areas might overlap; and,
-; the segment is moved upwards. Therefore, this code starts at the highest
+; into where it must be run (over the BSS segment). The two areas might overlap;
+; and, the segment is moved upwards. Therefore, this code starts at the highest
; address, and decrements to the lowest address. The low bytes of the starting
; pointers are not sums. The high bytes are sums; but, they do not include the
; carry. Both the low-byte sums and the carries will be done when the pointers
.importzp ptr1
-.segment "INIT"
+.code
zerobss:
lda #<__BSS_RUN__
; Done
L4: rts
-
-
-
; ------------------------------------------------------------------------
-.segment "ZPSAVE"
+.segment "INITBSS"
zpsave: .res zpspace
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
;---------------------------------------------------------------------------
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
+ lda #0 ; The terminating NUL character
ldy FNLEN
cpy #NAME_LEN + 1
bcc L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda (FNADR),y
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem," no args.
+ beq done ; No "rem," no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
.endproc
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2
irqcount: .byte 0
-.segment "ZPSAVE"
+.segment "INITBSS"
zpsave: .res zpspace
.import __argc, __argv
.include "plus4.inc"
-
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
+ lda #0 ; The terminating NUL character
ldy FNAM_LEN
cpy #NAME_LEN + 1
bcc L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda (FNAM),y
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem," no args.
+ beq done ; No "rem," no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
sta __argv
stx __argv + 1
rts
-
-; --------------------------------------------------------------------------
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2
-
;---------------------------------------------------------------------------
; Data
-.bss
-__argc: .res 2
-__argv: .res 2
+.data
+__argc: .word 0
+__argv: .addr 0
; ----------------------------------------------------------------------------
; Data
-.bss
+.segment "INITBSS"
; Initial stack pointer value. Stack is reset to this in case of overflows to
; allow program exit processing.
-initialsp: .word 0
+initialsp: .res 2
; Stack low water mark.
-lowwater: .word 0
+lowwater: .res 2
; ------------------------------------------------------------------------
-.segment "ZPSAVE"
+.segment "INITBSS"
zpsave: .res zpspace
.include "vic20.inc"
-
MAXARGS = 10 ; Maximum number of arguments allowed
REM = $8f ; BASIC token-code
-NAME_LEN = 16 ; maximum length of command-name
+NAME_LEN = 16 ; Maximum length of command-name
; Get possible command-line arguments. Goes into the special INIT segment,
; which may be reused after the startup code is run
; Assume that the program was loaded, a moment ago, by the traditional LOAD
; statement. Save the "most-recent filename" as argument #0.
-; Because the buffer, that we're copying into, was zeroed out,
-; we don't need to add a NUL character.
-;
+
+ lda #0 ; The terminating NUL character
ldy FNAM_LEN
cpy #NAME_LEN + 1
bcc L1
- ldy #NAME_LEN - 1 ; limit the length
+ ldy #NAME_LEN ; Limit the length
+ bne L1 ; Branch always
L0: lda (FNAM),y
- sta name,y
-L1: dey
+L1: sta name,y
+ dey
bpl L0
inc __argc ; argc always is equal to, at least, 1
; Find the "rem" token.
-;
+
ldx #0
L2: lda BASIC_BUF,x
- beq done ; no "rem," no args.
+ beq done ; No "rem," no args.
inx
cmp #REM
bne L2
beq done ; End of line reached
inx
cmp #' ' ; Skip leading spaces
- beq next ;
+ beq next
; Found start of next argument. We've incremented the pointer in X already, so
; it points to the second character of the argument. This is useful since we
stx __argv + 1
rts
-; These arrays are zeroed before initmainargs is called.
-; char name[16+1];
-; char* argv[MAXARGS+1]={name};
-;
-.bss
+.segment "INITBSS"
+
term: .res 1
name: .res NAME_LEN + 1
.data
+
+; char* argv[MAXARGS+1]={name};
argv: .addr name
.res MAXARGS * 2
-