Subversion Repositories SvarDOS

Rev

Rev 490 | Rev 519 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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