File: exec.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (211 lines) | stat: -rw-r--r-- 6,191 bytes parent folder | download | duplicates (3)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
;
; Christian Groessler, 12-Jun-2016
;
; int __fastcall__ exec (const char* progname, const char* cmdline);
;
; supports only XDOS at the moment

        .export         _exec

        .import         popax
        .import         __dos_type
        .import         findfreeiocb
        .import         incsp2
        .import         excexit                 ; from crt0.s
        .import         SP_save                 ; from crt0.s
.ifdef  UCASE_FILENAME
        .import         ucase_fn
        .import         addysp
.endif

        .include        "zeropage.inc"
        .include        "errno.inc"
        .include        "atari.inc"

; area $0100 to $0128 might be in use (e.g. Hias' high speed patch)
CMDLINE_BUFFER          =       $0129           ; put progname + cmdline as one single string there
; alternatively:
;CMDLINE_BUFFER          =       $0480           ; put progname + cmdline as one single string there
CMDLINE_MAX             =       40+3            ; max. length of drive + progname + cmdline

        .code

notsupp:lda     #ENOSYS         ; "unsupported system call"
        .byte   $2C             ; bit opcode, eats the next 2 bytes
noiocb: lda     #EMFILE         ; "too many open files"
        jsr     incsp2          ; clean up stack
seterr: jmp     __directerrno


; entry point

_exec:
        ; save cmdline
        sta     ptr3
        stx     ptr3+1

        ldy     __dos_type
        cpy     #XDOS
        bne     notsupp

        jsr     findfreeiocb
        bne     noiocb

        stx     tmp4            ; remember IOCB index

        ; get program name
        jsr     popax

.ifdef  UCASE_FILENAME
.ifdef  DEFAULT_DEVICE
        ldy     #$80
.else
        ldy     #$00
.endif
        sty     tmp2            ; set flag for ucase_fn
        jsr     ucase_fn
        bcc     ucok1
invret: lda     #EINVAL         ; file name is too long
        bne     seterr
ucok1:
.endif  ; defined UCASE_FILENAME

; copy program name and arguments to CMDLINE_BUFFER

        sta     ptr4            ; ptr4: pointer to program name
        stx     ptr4+1
        ldy     #0
        ; TODO: check stack ptr and and use min(CMDLINE_MAX,available_stack)
copyp:  lda     (ptr4),y
        beq     copypd
        sta     CMDLINE_BUFFER,y
        iny
        cpy     #CMDLINE_MAX
        bne     copyp

        ; programe name too long
        beq     invret

.ifndef  UCASE_FILENAME
invret: lda     #EINVAL
        bne     seterr
.endif

; file name copied, check for args

copypd: tya                     ; put Y into X (index into CMDLINE_BUFFER)
        tax
        lda     ptr3
        ora     ptr3+1          ; do we have arguments?
        beq     copycd          ; no
        ldy     #0
        lda     (ptr3),y        ; get first byte of cmdline parameter
        beq     copycd          ; nothing there...
        lda     #' '            ; add a space btw. progname and cmdline
        bne     copyc1

; copy args

copyc:  lda     (ptr3),y
        beq     copycd
        iny
copyc1: sta     CMDLINE_BUFFER,x
        inx
        cpx     #CMDLINE_MAX
        bne     copyc
        ; progname + arguments too long
        beq     invret

invexe: jsr     close
        lda     #XNTBIN
        bne     setmerr

copycd: lda     #ATEOL
        sta     CMDLINE_BUFFER,x

; open the program file, read the first two bytes and compare them to $FF

        ldx     tmp4            ; get IOCB index
        lda     ptr4            ; ptr4 points to progname
        sta     ICBAL,x
        lda     ptr4+1
        sta     ICBAH,x
        lda     #OPNIN          ; open for input
        sta     ICAX1,x
        lda     #OPEN
        sta     ICCOM,x
        jsr     CIOV

        tya

.ifdef  UCASE_FILENAME
        ldy     tmp3            ; get size
        jsr     addysp          ; free used space on the stack
        ; the following 'bpl' depends on 'addysp' restoring A as last command before 'rts'
.endif  ; defined UCASE_FILENAME

        bpl     openok
        pha                     ; remember error code
        jsr     close           ; close the IOCB (required even if open failed)
        pla                     ; put error code back into A
setmerr:jmp     __mappederrno   ; update errno from OS specific error code in A

openok: lda     #>buf
        sta     ICBAH,x         ; set buffer address
        lda     #<buf
        sta     ICBAL,x
        lda     #0              ; set buffer length
        sta     ICBLH,x
        lda     #2
        sta     ICBLL,x
        lda     #GETCHR         ; iocb command code
        sta     ICCOM,x
        jsr     CIOV            ; read it
        bmi     invexe          ; read operation failed, return error

        lda     ICBLL,x         ; # of bytes read
        cmp     #2
        bne     invexe
        lda     #$FF            ; check file format (need $FFFF at the beginning)
        cmp     buf
        bne     invexe
        cmp     buf+1
        bne     invexe

        jsr     close           ; close program file

; program file appears to be available and good
; here's the point of no return

        ldx     SP_save
        txs                     ; reset stack pointer to what it was at program entry
        lda     tmp4            ; get IOCB index
        pha                     ; and save it ('excexit' calls destructors and they might destroy tmp4)
        jsr     excexit         ; on atarixl this will enable the ROM again, making all high variables inaccessible
        pla
        tax                     ; IOCB index in X

        lda     #<CMDLINE_BUFFER
        sta     ICBAL,x         ; address
        lda     #>CMDLINE_BUFFER
        sta     ICBAH,x
        lda     #0
        sta     ICBLL,x         ; length shouldn't be random, but 0 is ok
        sta     ICBLH,x
        sta     ICAX1,x
        sta     ICAX2,x
        lda     #80             ; XDOS: run DUP command
        sta     ICCOM,x
        jmp     CIOV_org        ; no way to display an error message in case of failure, and we will return to DOS


; close IOCB, index in X
.proc   close
        lda    #CLOSE
        sta    ICCOM,x
        jmp    CIOV             ; close IOCB
.endproc

        .bss

buf:    .res    2