-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathMSDOS_A.ASM
293 lines (280 loc) · 6.02 KB
/
MSDOS_A.ASM
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
; Copyright (c) 1990,1991,1992 Chris and John Downey
_TEXT segment word public 'CODE'
db "@(#)msdos_a.asm 2.1 (Chris & John Downey) 7/29/92"
db 0
_TEXT ends
;***
;
; program name:
; xvi
; function:
; PD version of UNIX "vi" editor, with extensions.
; module name:
; msdos_a.asm
; module function:
; Assembly language part of system interface module for MS-DOS.
;
; This code has been assembled with Microsoft's Macro Assembler
; (MASM) version 5.1, & is compatible with code generated by
; MS-DOS C compilers using the normal large memory model calling
; conventions. This includes the Microsoft & Zortech compilers.
;
; The ignore_signals() routine installs handlers for keyboard &
; critical error interrupts. Critical error interrupts are
; generated for events like trying to access a diskette when
; there isn't one in the drive, or it isn't formatted, etc. The
; system's default interrupt handler just displays a message
; followed by "Abort, Retry, Fail?", which destroys our editing
; screen, & if the user presses 'a', the current process gets
; killed without further warning. We don't want this to happen
; to xvi, so we install our own handler, which just pretends the
; user chose the "Ignore" option (or "Fail" on MS-DOS 3.0 or
; later) by returning 0 (for "Ignore") or 3 (for "Fail") in the
; AL register.
;
; Note that most MS-DOS system calls, if issued from within a
; critical error handler, will cause the system to crash
; (because the system itself isn't re-entrant).
; history:
;
; STEVIE - ST Editor for VI Enthusiasts, Version 3.10
; Originally by Tim Thompson (twitch!tjt)
; Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
; Heavily modified by Chris & John Downey
;***
include 8086mm.inc
public _msdsignal
public _catch_signals
public _getchnw
public _dup
public _dup2
_TEXT segment word public 'CODE'
even
;
; Address of interrupt flag.
;
iflagaddr label dword
iflagoff dw ?
iflagseg dw ?
;
; Major MS-DOS version number.
;
sysversion db ?
assume nothing
assume cs:_TEXT
_msdsignal:
;
; void msdsignal(unsigned char *flagp);
;
; Install interrupt handlers.
;
; This routine is called by ignore_signals() with the
; address of the interrupt flag in flagp.
;
mov bx, sp
push ds
;
; Store address of interrupt flag.
;
if DPTRSIZE eq 4
lds ax, ss:[bx + CPTRSIZE]
else
mov ax, [bx + CPTRSIZE]
endif
mov dx, ds
mov cx, cs
mov ds, cx
assume ds: _TEXT
mov iflagoff, ax
mov iflagseg, dx
;
; Get MS-DOS major version number.
;
mov ah, 30h
int 21h
mov sysversion, al
;
; Install keyboard interrupt handler.
;
mov dx, offset kbd
mov ax, 2523h ; Keyboard interrupt is 23h.
int 21h
;
; Install critical error handler.
;
mov dx, offset criterr
mov ax, 2524h ; Critical error interrupt is 24h.
int 21h
pop ds
assume ds: nothing
C_ret
_catch_signals:
;
; void catch_signals(void);
;
; Set console break flag so that we can be interrupted
; even when we're not waiting for console input.
;
mov ax, 3301h
mov dl, 1
int 21h
C_ret
assume nothing
assume cs: _TEXT
criterr: ; Entry point for critical error interrupts.
pushf
sti
clear al
cmp sysversion, 3
jb ignore
mov al, 3
ignore:
popf
iret
kbd: ; Entry point for keyboard interrupts.
push ds
push bx
;
; Increment interrupt flag.
;
lds bx, iflagaddr
mov byte ptr [bx], 1
pop bx
pop ds
iret
assume nothing
assume cs: _TEXT
_getchnw:
;
; int getchnw();
;
; Return a character from standard input if one is
; immediately available, otherwise -1.
;
mov dl, 0ffh
mov ah, 6
int 21h
jz notavail
clear ah
C_ret
notavail:
mov ax, -1
C_ret
_dup:
;
; int dup(int fd);
;
; Duplicate file descriptor.
;
push bp
mov bp, sp
mov bx, [bp + CPTRSIZE + 2]
mov ah, 45h
int 21h
;
; Return -1 if CF is set, otherwise new descriptor.
;
sbb bx, bx
or ax, bx ; New descriptor is in AX.
pop bp
C_ret
_dup2:
;
; int dup2(int fd1, int fd2);
;
; Duplicate file descriptor with specified new value.
;
push bp
mov bp, sp
mov bx, [bp + CPTRSIZE + 2] ; Existing descriptor.
mov cx, [bp + CPTRSIZE + 4] ; New descriptor.
mov ah, 46h
int 21h
;
; Return -1 if CF is set, otherwise 0.
;
sbb ax, ax
pop bp
C_ret
;
; The following code is untested because neither of us has access to
; an MS-DOS development system at the moment.
;
; assume nothing
; assume cs: _TEXT
;
; setdta proc near
; ;
; ; Set DOS's Disk Transfer Address to the address
; ; pointed to by ss:bx. This is either a near or far
; ; pointer, depending on what C memory model we're
; ; using.
; ;
; mov ah, 1ah
; if DPTRSIZE eq 2 ; Small or medium memory model.
; mov dx, [bx]
; int 21h
; else
; push ds
; lds dx, ss:[bx]
; int 21h
; pop ds
; endif
; ret
; setdta endp
;
; _statfirst:
; ;
; ; int statfirst(char * name, struct dstat * info,
; ; int attribute);
; ;
; ; Return information on a named file or the first file
; ; matching a given specification.
; ;
; ; This is like stat(2) on Unix except that it does
; ; pattern matching with '*' & '?' (in the base name
; ; only, not in any directory names). If there are
; ; multiple matches, statfirst() only returns
; ; information on the first one & statnext() can be
; ; called successively for subsequent ones.
; ;
; ; The base name is returned, in capital letters, in
; ; the dstat structure, together with some other
; ; information.
; ;
; mov bx, sp
; add bx, CPTRSIZE + DPTRSIZE
; ;
; ; ss:bx now points to our struct dstat pointer.
; ;
; call setdta
; if DPTRSIZE eq 2
; mov dx, [bx - DPTRSIZE]
; mov cx, [bx + DPTRSIZE]
; else
; lds dx, ss:[bx - DPTRSIZE]
; mov cx, ss:[bx + DPTRSIZE]
; endif
; mov ah, 4eh
; int 21h
; sbb ax, ax
; C_ret
;
; _statnext:
; ;
; ; int statnext(struct dstat *info);
; ;
; ; See above.
; ;
; mov bx, sp
; add bx, CPTRSIZE
; ;
; ; ss:bx now points to our struct dstat pointer.
; ;
; call setdta
; mov ah, 4fh
; int 21h
; sbb ax, ax
; C_ret
_TEXT ends
end