-
Notifications
You must be signed in to change notification settings - Fork 1
/
runtime0.s
136 lines (114 loc) · 3.57 KB
/
runtime0.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
; Z80 CP/M CRT0 for SDCC
; 2013-12-16, 2014-05-26 William R Sowerbutts
.module runtime0
.globl _main
.globl l__INITIALIZER
.globl s__INITIALIZED
.globl s__INITIALIZER
.globl s__GSFINAL
.area _CODE
; this code is loaded at 0x100 by CP/M but is linked to run at 0x8000 above the
; bank switched memory region.
; copy ourselves to the right location.
booster:
; we're executing at 0x100
ld hl, #0x0100
ld de, #0x8000
ld bc, #(init_stackptr-0x8100)
ldir
; jump into the new copy
jp stage2
stage2:
; wipe out the original copy
ld de, #0x101
ld hl, #0x100
ld a, #0xe5
ld bc, #(init_stackptr-0x8101)
ld (hl), a
ldir
; and we're off!
init:
ld sp, #init_stackptr
; Initialise global variables
call gsinit
; Parse the command line
ld hl, #0x0081 ; first byte of command line
ld ix, #(argv_ptr+2) ; pointer to argument list in IX
ld iy, #1 ; we always have 1 argument (program name)
cmdnextarg:
ld b, h ; store pointer to start of argument in BC
ld c, l
cmdnextbyte:
ld a, (hl) ; read next command line byte
or a ; NUL -- end of command line?
jr z, endcmdline
cp #' ' ; space -- end of this argument?
jr z, cmdgotone
inc hl
jr cmdnextbyte ; loop
cmdgotone:
xor a ; replace space with NUL
ld (hl), a
call depositarg
inc hl
jr cmdnextarg
endcmdline:
call depositarg ; deposit final argument
ld hl, #argv_ptr ; pointer to argument list
push hl ; argv
push iy ; argc
; Call the C main() routine
call _main
; Terminate after main() returns
ld c, #0
call 5
depositarg:
ld a, (bc) ; is the argument empty?
or a
ret z ; it was empty -- no action
ld 0(ix), c ; store pointer
ld 1(ix), b
inc ix ; inc argv
inc ix
inc iy ; inc argc
ret
; Ordering of segments for the linker.
; WRS: Note we list all our segments here, even though
; we don't use them all, because ordering is set
; when they are first seen, it would appear.
.area _TPA
.area _HOME
.area _CODE
.area _INITIALIZER
.area _GSINIT
.area _GSFINAL
.area _DATA
.area _INITIALIZED
.area _BSEG
.area _STACK
.area _BSS
.area _HEAP
; ----------------------------------------
.area _STACK
; we keep argv[] in here as well, it grows up while the stack grows down
progname:
.ascii "CPMPROG"
.db 0
argv_ptr:
.dw #progname ; first entry of argv vector
.ds 256 ; stack memory
init_stackptr: ; this is the last thing the booster code will copy
; ----------------------------------------
.area _GSINIT
gsinit::
ld bc, #l__INITIALIZER
ld a, b
or a, c
jr z, gsinit_next
ld de, #s__INITIALIZED
ld hl, #s__INITIALIZER
ldir
gsinit_next:
; ----------------------------------------
.area _GSFINAL
ret