Subversion Repositories SvarDOS

Rev

Rev 520 | Rev 537 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
349 mateuszvis 1
;
2
; rmod - resident module of the SvarCOM command interpreter
3
;
4
; Copyright (C) 2021 Mateusz Viste
5
; MIT license
6
;
7
; this is installed in memory by the transient part of SvarCOM. it has only
8
; two jobs: providing a resident buffer for command history, environment, etc
9
; and respawning COMMAND.COM whenever necessary.
10
 
11
CPU 8086
459 mateuszvis 12
org 0x100
349 mateuszvis 13
 
459 mateuszvis 14
PSP_ENVSEG equ 0x2C
15
 
349 mateuszvis 16
section .text    ; all goes into code segment
17
 
350 mateuszvis 18
                 ; offset
19
SIG1 dw 0x1983   ;  +0
20
SIG2 dw 0x1985   ;  +2
21
SIG3 dw 0x2017   ;  +4
490 mateuszvis 22
SIG4 dw 0x2019   ;  +6  this acts also as a guardval to detect stack overflows
349 mateuszvis 23
 
490 mateuszvis 24
; DOS int 21h functions that I use require at least 40 bytes of stack under
25
; DOS-C (FreeDOS) kernel, so here I reserve 64 bytes juste to be sure
26
STACKBUF db "XXX  SVARCOM RMOD BY MATEUSZ VISTE  XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
27
STACKPTR dw 0
349 mateuszvis 28
 
366 mateuszvis 29
; offset of the COMSPEC variable in the environment block, 0 means "use
30
; boot drive". this value is patched by the transient part of COMMAND.COM
529 mateuszvis 31
COMSPECPTR dw 0  ; +4Ah
349 mateuszvis 32
 
366 mateuszvis 33
; fallback COMSPEC string used if no COMPSEC is present in the environment
34
; drive. drive is patched by the transient part of COMMAND.COM
529 mateuszvis 35
COMSPECBOOT db "@:\COMMAND.COM", 0 ; +4Ch
350 mateuszvis 36
 
529 mateuszvis 37
; exit code of last application
38
LEXCODE  db 0    ; +5Bh
39
 
460 mateuszvis 40
; ExecParamRec used by INT 21h, AX=4b00 (load and execute program), 14 bytes:
41
;  offset  size  content
42
;     +0     2   segment of environment for child (0 = current)
43
;     +2     4   address of command line to place at PSP:0080
44
;     +6     4   address of an FCB to be placed at PSP:005c
45
;    +0Ah    4   address of an FCB to be placed at PSP:006c
529 mateuszvis 46
EXEC_PARAM_REC db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0   ; +5Ch
366 mateuszvis 47
 
529 mateuszvis 48
; Program to execute, preset by SvarCOM (128 bytes, ASCIIZ)  ; +6Ah
461 mateuszvis 49
EXECPROG dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
460 mateuszvis 50
 
517 mateuszvis 51
; offset within EXECPROG for out and in filenames in case stdin or stdout
52
; needs to be redirected (0xffff=no redirection)
529 mateuszvis 53
REDIR_OUTFIL dw 0xffff    ; +EAh
54
REDIR_INFIL dw 0xffff     ; +ECh
55
REDIR_OUTAPPEND dw 0      ; +EEh
461 mateuszvis 56
 
529 mateuszvis 57
skipsig:         ; +F0h
517 mateuszvis 58
 
349 mateuszvis 59
; set up CS=DS=SS and point SP to my private stack buffer
60
mov ax, cs
61
mov ds, ax
62
mov es, ax
63
mov ss, ax
64
mov sp, STACKPTR
65
 
517 mateuszvis 66
; revert stdin/stdout redirections (if any) to their initial state
67
call REVERT_REDIR_IF_ANY
68
 
69
; redirect stdout if required
70
call REDIR_OUTFILE_IF_REQUIRED
71
 
460 mateuszvis 72
; should I executed command.com or a pre-set application?
73
or [EXECPROG], byte 0
74
jz EXEC_COMMAND_COM
75
 
461 mateuszvis 76
; TODO: perhaps I should call the DOS SetPSP function here? But if I do, the
77
;       int 21h, ah=50h call freezes...
78
;mov ah, 0x50           ; DOS 2+ -- Set PSP
79
;mov bx, cs
80
;int 0x21
460 mateuszvis 81
 
82
; exec an application preset (by SvarCOM) in the ExecParamRec
83
mov ax, 0x4B00         ; DOS 2+ - load & execute program
461 mateuszvis 84
mov dx, EXECPROG       ; DS:DX  - ASCIZ program name (preset at PSP[already)
460 mateuszvis 85
mov bx, EXEC_PARAM_REC ; ES:BX  - parameter block pointer
86
int 0x21
465 mateuszvis 87
mov [cs:EXECPROG], byte 0 ; do not run app again (+DS might have been changed)
460 mateuszvis 88
 
463 mateuszvis 89
jmp short skipsig      ; enforce valid ds/ss/etc (can be lost after int 21,4b)
90
 
460 mateuszvis 91
EXEC_COMMAND_COM:
92
 
353 mateuszvis 93
; collect the exit code of previous application
94
mov ah, 0x4D
95
int 0x21
529 mateuszvis 96
mov [LEXCODE], al
353 mateuszvis 97
 
460 mateuszvis 98
; zero out the exec param block (14 bytes)
99
mov al, 0              ; byte to write
100
mov cx, 14             ; how many times
101
mov di, EXEC_PARAM_REC ; ES:DI = destination
102
cld                    ; stosb must move forward
103
rep stosb              ; repeat cx times
104
 
366 mateuszvis 105
; preset the default COMSPEC pointer to ES:DX (ES is already set to DS)
106
mov dx, COMSPECBOOT
107
 
108
; do I have a valid COMSPEC?
109
or [COMSPECPTR], word 0
110
jz USEDEFAULTCOMSPEC
459 mateuszvis 111
; set ES:DX to actual COMSPEC (in env segment)
112
mov es, [PSP_ENVSEG]
366 mateuszvis 113
mov dx, [COMSPECPTR]
114
USEDEFAULTCOMSPEC:
115
 
349 mateuszvis 116
; prepare the exec param block
459 mateuszvis 117
mov ax, [PSP_ENVSEG]
350 mateuszvis 118
mov [EXEC_PARAM_REC], ax
465 mateuszvis 119
mov [EXEC_PARAM_REC+2], word CMDTAIL
442 mateuszvis 120
mov [EXEC_PARAM_REC+4], cs
349 mateuszvis 121
 
122
; execute command.com
123
mov ax, 0x4B00         ; DOS 2+ - load & execute program
366 mateuszvis 124
push es                ;
125
pop ds                 ;
126
;mov dx, COMSPEC       ; DS:DX  - ASCIZ program name (preset already)
127
push cs
128
pop es
349 mateuszvis 129
mov bx, EXEC_PARAM_REC ; ES:BX  - parameter block pointer
130
int 0x21
131
 
132
; if all went well, jump back to start
133
jnc skipsig
134
 
366 mateuszvis 135
; restore DS=CS
136
mov bx, cs
137
mov ds, bx
138
 
349 mateuszvis 139
; update error string so it contains the error number
140
add al, '0'
141
mov [ERRLOAD + 4], al
142
 
366 mateuszvis 143
; display error message
349 mateuszvis 144
mov ah, 0x09
145
mov dx, ERRLOAD
146
int 0x21
147
 
148
; wait for keypress
149
mov ah, 0x08
150
int 0x21
151
 
152
; back to program start
153
jmp skipsig
154
 
460 mateuszvis 155
; command.com tail arguments, in PSP format: length byte followed by args and
465 mateuszvis 156
; terminated with \r) - a single 0x0A byte is passed so SvarCOM knows it is
157
; called as respawn (as opposed to being invoked as a normal application)
158
; this allows multiple copies of SvarCOM to stack upon each other.
159
CMDTAIL db 0x01, 0x0A, 0x0D
442 mateuszvis 160
 
366 mateuszvis 161
ERRLOAD db "ERR x, FAILED TO LOAD COMMAND.COM", 13, 10, '$'
517 mateuszvis 162
 
163
; variables used to revert stdin/stdout to their initial state
164
OLD_STDOUT dw 0xffff
165
OLD_STDIN  dw 0xffff
166
 
167
 
520 mateuszvis 168
; ****************************************************************************
517 mateuszvis 169
; *** ROUTINES ***************************************************************
520 mateuszvis 170
; ****************************************************************************
517 mateuszvis 171
 
520 mateuszvis 172
; ----------------------------------------------------------------------------
517 mateuszvis 173
; revert stdin/stdout redirections (if any) to their initial state
174
; all memory accesses are CS-prefixes because this code may be called at
175
; times when DS is out of whack.
176
REVERT_REDIR_IF_ANY:
177
; is stdout redirected?
178
mov bx, [OLD_STDOUT]
179
cmp bx, 0xffff
180
je STDOUT_DONE
519 mateuszvis 181
; revert the stdout handle (dst in BX already)
517 mateuszvis 182
mov cx, 1        ; src handle (1=stdout)
183
mov ah, 0x46     ; redirect a handle
184
int 0x21
519 mateuszvis 185
; close the old handle (still in bx)
186
mov ah, 0x3e
187
int 0x21
517 mateuszvis 188
mov [OLD_STDOUT], word 0xffff ; mark stdout as "not redirected"
189
STDOUT_DONE:
190
ret
520 mateuszvis 191
; ----------------------------------------------------------------------------
517 mateuszvis 192
 
193
 
520 mateuszvis 194
; ----------------------------------------------------------------------------
517 mateuszvis 195
; redirect stdout if REDIR_OUTFIL points to something
196
REDIR_OUTFILE_IF_REQUIRED:
197
mov si, [REDIR_OUTFIL]
198
cmp si, 0xffff
199
je NO_STDOUT_REDIR
200
add si, EXECPROG       ; si=output file
201
mov ax, 0x6c00         ; Extended Open/Create
202
mov bx, 1              ; access mode (0=read, 1=write, 2=r+w)
203
xor cx, cx             ; file attribs when(if) file is created (0=normal)
204
mov dx, [REDIR_OUTAPPEND] ; action if file exist (0x11=open, 0x12=truncate)
205
int 0x21               ; ax=handle on success (CF clear)
206
mov [REDIR_OUTFIL], word 0xffff
207
jc NO_STDOUT_REDIR     ; TODO: abort with an error message instead
520 mateuszvis 208
 
209
; jump to end of file if flag was 0x11 (required for >> redirections)
210
cmp [REDIR_OUTAPPEND], word 0x11
211
jne SKIP_JMPEOF
212
mov bx, ax
213
mov ax, 0x4202         ; jump to position EOF - CX:DX in handle BX
214
xor cx, cx
215
xor dx, dx
216
int 0x21
217
mov ax, bx             ; put my handle back in ax, as expected by later code
218
SKIP_JMPEOF:
219
 
517 mateuszvis 220
; duplicate current stdout so I can revert it later
221
push ax                ; save my file handle in stack
222
mov ah, 0x45           ; duplicate file handle BX
223
mov bx, 1              ; 1=stdout
224
int 0x21               ; ax=new (duplicated) file handle
225
mov [OLD_STDOUT], ax   ; save the old handle in memory
520 mateuszvis 226
 
517 mateuszvis 227
; redirect stdout to my file
228
pop bx                 ; dst handle
229
mov cx, 1              ; src handle (1=stdout)
230
mov ah, 0x46           ; "redirect a handle"
231
int 0x21
520 mateuszvis 232
 
517 mateuszvis 233
; close the original file handle, I no longer need it
234
mov ah, 0x3e           ; close a file handle (handle in BX)
519 mateuszvis 235
int 0x21
517 mateuszvis 236
NO_STDOUT_REDIR:
237
ret
520 mateuszvis 238
; ----------------------------------------------------------------------------