2 ; MSCODE.ASM -- MSDOS code
8 CODE SEGMENT BYTE PUBLIC 'CODE'
9 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
37 i_need CURRENTPDB
,WORD
48 i_need NULLDEVPT
,DWORD
51 i_need OEM_HANDLER
,DWORD
54 EXTRN DSKSTATCHK
:NEAR,GETBP
:NEAR,DSKREAD
:NEAR,DSKWRITE
:NEAR
57 BREAK <Copyright notice
and version
>
64 HEADER
DB 13,10,"Microsoft MS-DOS version "
65 DB DOS_MAJOR_VERSION
+ "0"
67 DB (DOS_MINOR_VERSION
/ 10) + "0"
68 DB (DOS_MINOR_VERSION
MOD 10) + "0"
75 HEADER
DB 13,10,82h
,"M"+1fh
,82h
,"i"+20h
,82h
,"c"+20h
,82h
,"r"+20h
,82h
,"o"+20h
76 DB 82h
,"s"+20h
,82h
,"o"+20h
,82h
,"f"+20h
,82h
,"t"+20h
77 DB 81h
,40h
,82h
,"M"+1fh
,82h
,"S"+1fh
,81h
,5
dh+1fh
78 DB 82h
,"D"+1fh
,82h
,"O"+1fh
,82h
,"S"+1fh
,81h
,40h
79 DB 82h
,DOS_MAJOR_VERSION
+"0"+1fh
81 DB 82h
,(DOS_MINOR_VERSION
/ 10)+"0"+1fh
82 DB 82h
,(DOS_MINOR_VERSION
MOD 10)+"0"+1fh
86 DB "Copyright 1981,82,83 Microsoft Corp.",13,10,"$"
88 BREAK <System
call entry points
and dispatcher
>
89 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
91 procedure SYSTEM_CALL
,NEAR
92 entry QUIT
; INT 20H entry point
96 entry COMMAND
; Interrupt call entry point (INT 21H)
99 CMP AH,SET_OEM_HANDLER
112 entry CALL_ENTRY
; System call entry point and dispatcher
113 POP AX ; IP from the long call at 5
114 POP AX ; Segment from the long call at 5
115 POP [User_SP
] ; IP from the CALL 5
116 PUSHF ; Start re-ordering the stack
118 PUSH AX ; Save segment
119 PUSH [User_SP
] ; Stack now ordered as if INT had been used
120 CMP CL,MAXCALL
; This entry point doesn't get as many calls
130 INC [INDOS
] ; Flag that we're in the DOS
140 ; save user stack in his area for later returns (possibly from EXEC)
141 ; Here comes multitasking!!!
144 MOV WORD PTR DS:[PDB_User_stack
],SP
145 MOV WORD PTR DS:[PDB_User_stack
+2],SS
147 MOV BX,CS ; no holes here.
152 MOV SP,OFFSET DOSGROUP
:AUXSTACK
; Enough stack for interrupts
159 MOV BYTE PTR [NoSetDir
],0 ; set directories on search
166 JBE IOROUT
; Character I/O
167 CMP AH,GET_CURRENT_PDB
; INT 24 needs GET,SET PDB
169 CMP AH,SET_CURRENT_PDB
173 JNZ DISPCALL
; Stay on AUXSTACK if INT 24
174 MOV SP,OFFSET DOSGROUP
:IOSTACK
178 MOV [ERRORMODE
],0 ; Cannot make non 1-12 calls in
179 MOV [WPERR
],-1 ; error mode, so good place to
180 ; make sure flags are reset
181 MOV SP,OFFSET DOSGROUP
:DSKSTACK
189 PUSH CS:[BX+DISPATCH
]
196 ASSUME
SS:NOTHING
; User routines may misbehave
202 MOV BYTE PTR [BP.user_AX
],AL
213 ; restore_world restores all registers ('cept SS:SP, CS:IP, flags) from
214 ; the stack prior to giving the user control
216 ASSUME
DS:NOTHING
,ES:NOTHING
218 procedure restore_world
,NEAR
219 POP restore_tmp
; POP restore_tmp
230 PUSH restore_tmp
; PUSH restore_tmp
235 ; save_world saves complete registers on the stack
237 procedure save_world
,NEAR
252 ; get_user_stack returns the user's stack (and hence registers) in DS:SI
254 procedure get_user_stack
,NEAR
255 LDS SI,DWORD PTR [user_SP
]
262 short_addr $ABORT
; 0 0
264 short_addr $STD_CON_INPUT
; 1 1
265 short_addr $STD_CON_OUTPUT
; 2 2
266 short_addr $STD_AUX_INPUT
; 3 3
267 short_addr $STD_AUX_OUTPUT
; 4 4
268 short_addr $STD_PRINTER_OUTPUT
; 5 5
269 short_addr $RAW_CON_IO
; 6 6
270 short_addr $RAW_CON_INPUT
; 7 7
271 short_addr $STD_CON_INPUT_NO_ECHO
; 8 8
272 short_addr $STD_CON_STRING_OUTPUT
; 9 9
273 short_addr $STD_CON_STRING_INPUT
; 10 A
274 short_addr $STD_CON_INPUT_STATUS
; 11 B
275 short_addr $STD_CON_INPUT_FLUSH
; 12 C
276 short_addr $DISK_RESET
; 13 D
277 short_addr $SET_DEFAULT_DRIVE
; 14 E
278 short_addr $FCB_OPEN
; 15 F
279 short_addr $FCB_CLOSE
; 16 10
280 short_addr $DIR_SEARCH_FIRST
; 17 11
281 short_addr $DIR_SEARCH_NEXT
; 18 12
282 short_addr $FCB_DELETE
; 19 13
283 short_addr $FCB_SEQ_READ
; 20 14
284 short_addr $FCB_SEQ_WRITE
; 21 15
285 short_addr $FCB_CREATE
; 22 16
286 short_addr $FCB_RENAME
; 23 17
287 short_addr CPMFUNC
; 24 18
288 short_addr $GET_DEFAULT_DRIVE
; 25 19
289 short_addr $SET_DMA
; 26 1A
291 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
292 ; C A V E A T P R O G R A M M E R ;
294 short_addr $SLEAZEFUNC
; 27 1B
295 short_addr $SLEAZEFUNCDL
; 28 1C
297 ; C A V E A T P R O G R A M M E R ;
298 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
300 short_addr CPMFUNC
; 29 1D
301 short_addr CPMFUNC
; 30 1E
302 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
303 ; C A V E A T P R O G R A M M E R ;
305 short_addr $GET_DEFAULT_DPB
; 31 1F
307 ; C A V E A T P R O G R A M M E R ;
308 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
309 short_addr CPMFUNC
; 32 20
310 short_addr $FCB_RANDOM_READ
; 33 21
311 short_addr $FCB_RANDOM_WRITE
; 34 22
312 short_addr $GET_FCB_FILE_LENGTH
; 35 23
313 short_addr $GET_FCB_POSITION
; 36 24
314 MAXCALL
= ($-DISPATCH
)/2 - 1
317 short_addr $SET_INTERRUPT_VECTOR
; 37 25
318 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
319 ; C A V E A T P R O G R A M M E R ;
321 short_addr $CREATE_PROCESS_DATA_BLOCK
; 38 26
323 ; C A V E A T P R O G R A M M E R ;
324 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
325 short_addr $FCB_RANDOM_READ_BLOCK
; 39 27
326 short_addr $FCB_RANDOM_WRITE_BLOCK
; 40 28
327 short_addr $PARSE_FILE_DESCRIPTOR
; 41 29
328 short_addr $GET_DATE
; 42 2A
329 short_addr $SET_DATE
; 43 2B
330 short_addr $GET_TIME
; 44 2C
331 short_addr $SET_TIME
; 45 2D
332 short_addr $SET_VERIFY_ON_WRITE
; 46 2E
334 ; Extended functionality group
335 short_addr $GET_DMA
; 47 2F
336 short_addr $GET_VERSION
; 48 30
337 short_addr $Keep_Process
; 49 31
338 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
339 ; C A V E A T P R O G R A M M E R ;
341 short_addr $GET_DPB
; 50 32
343 ; C A V E A T P R O G R A M M E R ;
344 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
345 short_addr $SET_CTRL_C_TRAPPING
; 51 33
346 short_addr $GET_INDOS_FLAG
; 52 34
347 short_addr $GET_INTERRUPT_VECTOR
; 53 35
348 short_addr $GET_DRIVE_FREESPACE
; 54 36
349 short_addr $CHAR_OPER
; 55 37
350 short_addr $INTERNATIONAL
; 56 38
353 short_addr $MKDIR
; 57 39
354 short_addr $RMDIR
; 58 3A
355 short_addr $CHDIR
; 59 3B
357 short_addr $CREAT
; 60 3C
358 short_addr $OPEN
; 61 3D
359 short_addr $CLOSE
; 62 3E
360 short_addr $READ
; 63 3F
361 short_addr $WRITE
; 64 40
362 short_addr $UNLINK
; 65 41
363 short_addr $LSEEK
; 66 42
364 short_addr $CHMOD
; 67 43
365 short_addr $IOCTL
; 68 44
366 short_addr $
DUP ; 69 45
367 short_addr $DUP2
; 70 46
368 short_addr $CURRENT_DIR
; 71 47
370 short_addr $ALLOC
; 72 48
371 short_addr $DEALLOC
; 73 49
372 short_addr $SETBLOCK
; 74 4A
374 short_addr $EXEC
; 75 4B
375 short_addr $EXIT
; 76 4C
376 short_addr $
WAIT ; 77 4D
377 short_addr $FIND_FIRST
; 78 4E
379 short_addr $FIND_NEXT
; 79 4F
380 ; SPECIAL SYSTEM GROUP
381 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
382 ; C A V E A T P R O G R A M M E R ;
384 short_addr $SET_CURRENT_PDB
; 80 50
385 short_addr $GET_CURRENT_PDB
; 81 51
386 short_addr $GET_IN_VARS
; 82 52
387 short_addr $SETDPB
; 83 53
389 ; C A V E A T P R O G R A M M E R ;
390 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
391 short_addr $GET_VERIFY_ON_WRITE
; 84 54
392 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
393 ; C A V E A T P R O G R A M M E R ;
395 short_addr $DUP_PDB
; 85 55
397 ; C A V E A T P R O G R A M M E R ;
398 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
399 short_addr $RENAME
; 86 56
400 short_addr $FILE_TIMES
; 87 57
401 short_addr $AllocOper
; 88 58
403 MAXCOM
= ($-DISPATCH
)/2 - 1
410 BREAK <Set_OEM_Handler
-- Set OEM sys
call address
and handle OEM Calls
>
413 ASSUME
DS:NOTHING
,ES:NOTHING
416 ; User registers, User Stack, INTS disabled
417 ; If CALL F8, DS:DX is new handler address
419 ; Process OEM INT 21 extensions
421 ; Jumps to OEM_HANDLER if appropriate
423 JNE DO_OEM_FUNC
; If above F8 try to jump to handler
424 MOV WORD PTR [OEM_HANDLER
],DX ; Set Handler
425 MOV WORD PTR [OEM_HANDLER
+2],DS
426 IRET ; Quick return, Have altered no registers
429 CMP WORD PTR [OEM_HANDLER
],-1
431 JMP BADCALL
; Handler not initialized
442 ; $Set_current_PDB takes BX and sets it to be the current process
443 ; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
445 procedure $SET_CURRENT_PDB
,NEAR
446 ASSUME
DS:NOTHING
,SS:NOTHING
449 $SET_CURRENT_PDB ENDP
452 ; $get_current_PDB returns in BX the current process
453 ; *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
455 procedure $GET_CURRENT_PDB
,NEAR
456 ASSUME
DS:NOTHING
,SS:NOTHING
457 invoke get_user_stack
461 $GET_CURRENT_PDB ENDP
463 ; C A V E A T P R O G R A M M E R ;
464 ;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
466 BREAK <NullDev
-- Driver for null device
>
467 procedure SNULDEV
,FAR
468 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
469 MOV WORD PTR [NULLDEVPT
],BX
470 MOV WORD PTR [NULLDEVPT
+2],ES
474 procedure INULDEV
,FAR
478 OR ES:[BX.REQSTAT
],STDON
; Set done bit
486 BREAK <AbsDRD
, AbsDWRT
-- INT int_disk_read
, int_disk_write handlers
>>
490 ERRIN: ; Codes returned by BIOS
493 DB 12 ; GENERAL ERROR
495 DB 8 ; SECTOR NOT FOUND
496 DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK
497 ERROUT: ; DISK ERRORS RETURNED FROM INT 25 and 26
499 DB 40H
; Seek failure
500 DB 2 ; Address Mark not found
502 DB 4 ; SECTOR NOT FOUND
503 DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK
509 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
517 MOV SP,OFFSET DOSGROUP
:DSKSTACK
535 ; Translate the error code to ancient 1.1 codes
539 XOR AH,AH ; Nul error code
540 MOV CX,NUMERR
; Number of possible error conditions
541 MOV DI,OFFSET DOSGROUP
:ERRIN
; Point to error conditions
543 JNZ LEAVECODE
; Not found
544 MOV AH,ES:[DI+NUMERR
-1] ; Get translation
561 procedure ABSDWRT
,FAR
562 ASSUME
DS:NOTHING
,ES:NOTHING
,SS:NOTHING
570 MOV SP,OFFSET DOSGROUP
:DSKSTACK
589 procedure SYS_RETURN
,NEAR
590 ASSUME
DS:NOTHING
,ES:NOTHING
599 XOR AH,AH ; hack to allow for smaller error rets
605 MOV [SI.user_AX
],AX ; Really only sets AH
607 POP [SI.user_F
] ; dump on his flags