summaryrefslogtreecommitdiff
path: root/v2.0/source/MISC.ASM
diff options
context:
space:
mode:
authorGravatar Rich Turner1983-08-12 17:53:34 -0700
committerGravatar Rich Turner2018-09-21 17:53:34 -0700
commit80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 (patch)
treeee4357f7f3dd0f2ded59b9c6e7384432d85e7ec9 /v2.0/source/MISC.ASM
parentMS-DOS v1.25 Release (diff)
downloadms-dos-80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6.tar.gz
ms-dos-80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6.tar.xz
ms-dos-80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6.zip
MS-DOS v2.0 Release
Diffstat (limited to 'v2.0/source/MISC.ASM')
-rw-r--r--v2.0/source/MISC.ASM648
1 files changed, 648 insertions, 0 deletions
diff --git a/v2.0/source/MISC.ASM b/v2.0/source/MISC.ASM
new file mode 100644
index 0000000..e0a5cee
--- /dev/null
+++ b/v2.0/source/MISC.ASM
@@ -0,0 +1,648 @@
1TITLE MISC - Miscellanious routines for MS-DOS
2NAME MISC
3;
4; Miscellaneous system calls most of which are CAVEAT
5;
6; $SLEAZEFUNC
7; $SLEAZEFUNCDL
8; $GET_INDOS_FLAG
9; $GET_IN_VARS
10; $GET_DEFAULT_DPB
11; $GET_DPB
12; $DISK_RESET
13; $SETDPB
14; $Dup_PDB
15; $CREATE_PROCESS_DATA_BLOCK
16; SETMEM
17;
18.xlist
19;
20; get the appropriate segment definitions
21;
22INCLUDE DOSSEG.ASM
23
24CODE SEGMENT BYTE PUBLIC 'CODE'
25 ASSUME SS:DOSGROUP,CS:DOSGROUP
26
27.xcref
28INCLUDE DOSSYM.ASM
29INCLUDE DEVSYM.ASM
30.cref
31.list
32
33
34ifndef Kanji
35Kanji equ 0
36endif
37
38ENTRYPOINTSEG EQU 0CH
39MAXDIF EQU 0FFFH
40SAVEXIT EQU 10
41
42 i_need LASTBUFFER,DWORD
43 i_need INDOS,BYTE
44 i_need SYSINITVAR,BYTE
45 i_need CurrentPDB,WORD
46 i_need CreatePDB,BYTE
47 i_need EXIT_TYPE,BYTE
48 i_need EXIT_CODE,WORD
49 i_need LASTENT,WORD
50 i_need THISDPB,DWORD
51 i_need ATTRIB,BYTE
52 i_need EXTFCB,BYTE
53 i_need DMAADD,DWORD
54 i_need DIRSTART,WORD
55 i_need CURBUF,DWORD
56 i_need USER_SP,WORD
57 i_need ENTLAST,WORD
58 i_need THISDRV,BYTE
59
60ASSUME SS:DOSGROUP
61
62BREAK <SleazeFunc -- get a pointer to media byte>
63
64;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
65; C A V E A T P R O G R A M M E R ;
66; ;
67 procedure $SLEAZEFUNC,NEAR
68ASSUME DS:NOTHING,ES:NOTHING
69
70; Inputs:
71; None
72; Function:
73; Return Stuff sort of like old get fat call
74; Outputs:
75; DS:BX = Points to FAT ID byte (IBM only)
76; GOD help anyone who tries to do ANYTHING except
77; READ this ONE byte.
78; DX = Total Number of allocation units on disk
79; CX = Sector size
80; AL = Sectors per allocation unit
81; = -1 if bad drive specified
82
83 MOV DL,0
84 entry $SLEAZEFUNCDL
85 PUSH SS
86 POP DS
87ASSUME DS:DOSGROUP
88 MOV AL,DL
89 invoke GETTHISDRV
90 MOV AL,-1
91 JC BADSLDRIVE
92 invoke FATREAD
93 MOV DX,ES:[BP.dpb_max_cluster]
94 DEC DX
95 MOV AL,ES:[BP.dpb_cluster_mask]
96 INC AL
97 MOV CX,ES:[BP.dpb_sector_size]
98 ADD BP,dpb_media
99BADSLDRIVE:
100 invoke get_user_stack
101ASSUME DS:NOTHING
102 MOV [SI.user_CX],CX
103 MOV [SI.user_DX],DX
104 MOV [SI.user_BX],BP
105 MOV [SI.user_DS],ES
106 return
107$SLEAZEFUNC ENDP
108; ;
109; C A V E A T P R O G R A M M E R ;
110;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
111
112
113
114BREAK <$ABORT -- Terminate a process>
115 procedure $ABORT,NEAR
116ASSUME DS:NOTHING,ES:NOTHING
117
118; Inputs:
119; CS:00 must point to valid program header block
120; Function:
121; Restore terminate and Cntrl-C addresses, flush buffers
122; and transfer to the terminate address
123; Returns:
124; TO THE TERMINATE ADDRESS
125
126 XOR AL,AL
127 MOV [exit_type],exit_abort
128
129;
130; abort_inner must have AL set as the exit code!
131;
132 entry abort_inner
133 MOV AH,[exit_type]
134 MOV [exit_code],AX
135 invoke Get_user_stack
136 MOV DS,[SI.user_CS] ; set up old interrupts
137 XOR AX,AX
138 MOV ES,AX
139 MOV SI,SAVEXIT
140 MOV DI,addr_int_terminate
141 MOVSW
142 MOVSW
143 MOVSW
144 MOVSW
145 MOVSW
146 MOVSW
147 transfer reset_environment
148$ABORT ENDP
149
150BREAK <$Dir_Search_First -- Start a directory search>
151 procedure $DIR_SEARCH_FIRST,NEAR
152ASSUME DS:NOTHING,ES:NOTHING
153
154; Inputs:
155; DS:DX Points to unopenned FCB
156; Function:
157; Directory is searched for first matching entry and the directory
158; entry is loaded at the disk transfer address
159; Returns:
160; AL = -1 if no entries matched, otherwise 0
161
162 invoke GETFILE
163ASSUME DS:DOSGROUP
164SAVPLCE:
165; Search-for-next enters here to save place and report
166; findings.
167 MOV DL,0 ; Do not XOR!!!
168 JC KILLSRCH
169 OR AH,AH ; Is it I/O device?
170 JS KILLIT ; If so, sign bit will end search
171 MOV AX,[LASTENT]
172 INC DL
173KILLIT:
174 MOV ES:[DI.FILDIRENT],AX
175 MOV AX,WORD PTR [THISDPB]
176 MOV ES:[DI.fcb_DRVBP],AX
177 MOV AX,WORD PTR [THISDPB+2]
178 MOV ES:[DI.fcb_DRVBP+2],AX
179 MOV AX,[DIRSTART]
180 MOV ES:[DI.fcb_DRVBP+4],AX
181; Information in directory entry must be copied into the first
182; 33 bytes starting at the disk transfer address.
183 MOV SI,BX
184 LES DI,[DMAADD]
185 MOV AX,00FFH
186 CMP AL,[EXTFCB]
187 JNZ NORMFCB
188 STOSW
189 INC AL
190 STOSW
191 STOSW
192 MOV AL,[ATTRIB]
193 STOSB
194NORMFCB:
195 MOV AL,[THISDRV]
196 INC AL
197 STOSB ; Set drive number
198 OR DL,DL
199 JZ DOSRELATIVE
200 MOV DS,WORD PTR [CURBUF+2]
201ASSUME DS:NOTHING
202DOSRELATIVE:
203
204 IF KANJI
205 MOVSW
206 CMP BYTE PTR ES:[DI-2],5
207 JNZ NOTKTRAN
208 MOV BYTE PTR ES:[DI-2],0E5H
209NOTKTRAN:
210 MOV CX,15
211 ELSE
212 MOV CX,16
213 ENDIF
214
215 REP MOVSW ; Copy 32 bytes of directory entry
216 XOR AL,AL
217 return
218
219ASSUME DS:NOTHING
220KILLSRCH1:
221 PUSH DS
222 POP ES ; Make ES:DI point to the FCB
223KILLSRCH:
224 MOV AX,-1
225 MOV WORD PTR ES:[DI.FILDIRENT],AX
226 return
227$DIR_SEARCH_FIRST ENDP
228
229BREAK <$Dir_Search_Next -- Find next matching directory entry>
230 procedure $DIR_SEARCH_NEXT,NEAR
231ASSUME DS:NOTHING,ES:NOTHING
232
233; Inputs:
234; DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
235; Function:
236; Directory is searched for the next matching entry and the directory
237; entry is loaded at the disk transfer address
238; Returns:
239; AL = -1 if no entries matched, otherwise 0
240
241 invoke MOVNAMENOSET
242ASSUME ES:DOSGROUP
243 MOV DI,DX
244 JC NEAR PTR KILLSRCH1
245 MOV AX,[DI.FILDIRENT]
246 LES BP,DWORD PTR [DI.fcb_DRVBP]
247 OR AX,AX
248 JS NEAR PTR KILLSRCH1
249 MOV BX,[DI.fcb_DRVBP+4]
250 PUSH DX
251 PUSH DS
252 PUSH AX
253 MOV WORD PTR [THISDPB],BP
254 MOV WORD PTR [THISDPB+2],ES
255 invoke SetDirSrch
256 ASSUME DS:DOSGROUP
257 POP AX
258 MOV [ENTLAST],-1
259 invoke GetEnt
260 invoke NextEnt
261 POP ES
262 ASSUME ES:NOTHING
263 POP DI
264 JMP SAVPLCE
265$DIR_SEARCH_NEXT ENDP
266
267BREAK <$Get_FCB_File_Length -- Return size of file in current records>
268 procedure $GET_FCB_FILE_LENGTH,NEAR
269ASSUME DS:NOTHING,ES:NOTHING
270
271; Inputs:
272; DS:DX points to unopenned FCB
273; Function:
274; Set random record field to size of file
275; Returns:
276; AL = -1 if no entries matched, otherwise 0
277
278 invoke GETFILE
279ASSUME DS:DOSGROUP
280 MOV AL,-1
281 retc
282 ADD DI,fcb_RR ; Write size in RR field
283 MOV CX,WORD PTR ES:[DI.fcb_RECSIZ-fcb_RR]
284 OR CX,CX
285 JNZ RECOK
286 MOV CX,128
287RECOK:
288 XOR DX,DX ; Intialize size to zero
289 INC SI
290 INC SI ; Point to length field
291 MOV DS,WORD PTR [CURBUF+2]
292ASSUME DS:NOTHING
293 MOV AX,[SI+2] ; Get high word of size
294 DIV CX
295 PUSH AX ; Save high part of result
296 LODSW ; Get low word of size
297 DIV CX
298 OR DX,DX ; Check for zero remainder
299 POP DX
300 JZ DEVSIZ
301 INC AX ; Round up for partial record
302 JNZ DEVSIZ ; Propagate carry?
303 INC DX
304DEVSIZ:
305 STOSW
306 MOV AX,DX
307 STOSB
308 MOV AL,0
309 CMP CX,64
310 JAE RET14 ; Only 3-byte field if fcb_RECSIZ >= 64
311 MOV ES:[DI],AH
312RET14: return
313$GET_FCB_FILE_LENGTH ENDP
314
315BREAK <$Get_Fcb_Position -- Set random record field to current position>
316 procedure $GET_FCB_POSITION,NEAR
317ASSUME DS:NOTHING,ES:NOTHING
318
319; Inputs:
320; DS:DX points to openned FCB
321; Function:
322; Sets random record field to be same as current record fields
323; Returns:
324; None
325
326 invoke GETREC
327 MOV WORD PTR [DI+fcb_RR],AX
328 MOV [DI+fcb_RR+2],DL
329 CMP [DI.fcb_RECSIZ],64
330 JAE RET16
331 MOV [DI+fcb_RR+2+1],DH ; Set 4th byte only if record size < 64
332RET16: return
333$GET_FCB_POSITION ENDP
334
335BREAK <$Disk_Reset -- Flush out all dirty buffers>
336 procedure $DISK_RESET,NEAR
337ASSUME DS:NOTHING,ES:NOTHING
338
339; Inputs:
340; None
341; Function:
342; Flush and invalidate all buffers
343; Returns:
344; Nothing
345
346 PUSH SS
347 POP DS
348ASSUME DS:DOSGROUP
349 MOV AL,-1
350 invoke FLUSHBUF
351 MOV WORD PTR [LASTBUFFER+2],-1
352 MOV WORD PTR [LASTBUFFER],-1
353 invoke SETVISIT
354ASSUME DS:NOTHING
355NBFFR: ; Free ALL buffers
356 MOV [DI.VISIT],1 ; Mark as visited
357 CMP BYTE PTR [DI.BUFDRV],-1
358 JZ SKPBF ; Save a call to PLACEBUF
359 MOV WORD PTR [DI.BUFDRV],00FFH
360 invoke SCANPLACE
361SKPBF:
362 invoke SKIPVISIT
363 JNZ NBFFR
364 return
365$DISK_RESET ENDP
366
367 procedure $RAW_CON_IO,NEAR ; System call 6
368ASSUME DS:NOTHING,ES:NOTHING
369
370; Inputs:
371; DL = -1 if input
372; else DL is output character
373; Function:
374; Input or output raw character from console, no echo
375; Returns:
376; AL = character
377
378 MOV AL,DL
379 CMP AL,-1
380 JNZ RAWOUT
381 LES DI,DWORD PTR [user_SP] ; Get pointer to register save area
382 XOR BX,BX
383 invoke GET_IO_FCB
384 retc
385 MOV AH,1
386 invoke IOFUNC
387 JNZ RESFLG
388 invoke SPOOLINT
389 OR BYTE PTR ES:[DI.user_F],40H ; Set user's zero flag
390 XOR AL,AL
391 return
392
393RESFLG:
394 AND BYTE PTR ES:[DI.user_F],0FFH-40H ; Reset user's zero flag
395
396RILP:
397 invoke SPOOLINT
398 entry $RAW_CON_INPUT ; System call 7
399
400; Inputs:
401; None
402; Function:
403; Input raw character from console, no echo
404; Returns:
405; AL = character
406
407 XOR BX,BX
408 invoke GET_IO_FCB
409 retc
410 MOV AH,1
411 invoke IOFUNC
412 JZ RILP
413 XOR AH,AH
414 invoke IOFUNC
415 return
416;
417; Output the character in AL to stdout
418;
419entry RAWOUT
420
421 PUSH BX
422 MOV BX,1
423
424 invoke GET_IO_FCB
425 JC RAWRET1
426
427 TEST [SI.fcb_DEVID],080H ; output to file?
428 JZ RAWNORM ; if so, do normally
429 PUSH DS
430 PUSH SI
431 LDS SI,DWORD PTR [SI.fcb_FIRCLUS] ; output to special?
432 TEST BYTE PTR [SI+SDEVATT],ISSPEC
433 POP SI
434 POP DS
435 JZ RAWNORM ; if not, do normally
436 INT int_fastcon ; quickly output the char
437 JMP SHORT RAWRET
438RAWNORM:
439
440 CALL RAWOUT3
441RAWRET: CLC
442RAWRET1:
443 POP BX
444 return
445
446;
447; Output the character in AL to handle in BX
448;
449entry RAWOUT2
450
451 invoke GET_IO_FCB
452 retc
453RAWOUT3:
454 PUSH AX
455 JMP SHORT RAWOSTRT
456ROLP:
457 invoke SPOOLINT
458RAWOSTRT:
459 MOV AH,3
460 CALL IOFUNC
461 JZ ROLP
462 POP AX
463 MOV AH,2
464 CALL IOFUNC
465 CLC ; Clear carry indicating successful
466 return
467$RAW_CON_IO ENDP
468
469ASSUME DS:NOTHING,ES:NOTHING
470; This routine is called at DOS init
471
472 procedure OUTMES,NEAR ; String output for internal messages
473 LODS CS:BYTE PTR [SI]
474 CMP AL,"$"
475 retz
476 invoke OUT
477 JMP SHORT OUTMES
478 return
479OutMes ENDP
480 ASSUME SS:DOSGROUP
481
482BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB>
483 procedure $PARSE_FILE_DESCRIPTOR,NEAR
484ASSUME DS:NOTHING,ES:NOTHING
485
486; Inputs:
487; DS:SI Points to a command line
488; ES:DI Points to an empty FCB
489; Bit 0 of AL = 1 At most one leading separator scanned off
490; = 0 Parse stops if separator encountered
491; Bit 1 of AL = 1 If drive field blank in command line - leave FCB
492; = 0 " " " " " " - put 0 in FCB
493; Bit 2 of AL = 1 If filename field blank - leave FCB
494; = 0 " " " - put blanks in FCB
495; Bit 3 of AL = 1 If extension field blank - leave FCB
496; = 0 " " " - put blanks in FCB
497; Function:
498; Parse command line into FCB
499; Returns:
500; AL = 1 if '*' or '?' in filename or extension, 0 otherwise
501; DS:SI points to first character after filename
502
503 invoke MAKEFCB
504 PUSH SI
505 invoke get_user_stack
506 POP [SI.user_SI]
507 return
508$PARSE_FILE_DESCRIPTOR ENDP
509
510BREAK <$Create_Process_Data_Block,SetMem -- Set up process data block>
511;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
512; C A V E A T P R O G R A M M E R ;
513; ;
514 procedure $Dup_PDB,NEAR
515ASSUME DS:NOTHING,ES:NOTHING
516 MOV BYTE PTR [CreatePDB], 0FFH ; indicate a new process
517$Dup_PDB ENDP
518
519
520 procedure $CREATE_PROCESS_DATA_BLOCK,NEAR
521ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
522
523; Inputs:
524; DX = Segment number of new base
525; Function:
526; Set up program base and copy term and ^C from int area
527; Returns:
528; None
529; Called at DOS init
530
531 MOV ES,DX
532 TEST BYTE PTR [CreatePDB],0FFh
533 JZ create_PDB_old
534 MOV DS,[CurrentPDB]
535 JMP SHORT Create_copy
536
537Create_PDB_old:
538 invoke get_user_stack
539 MOV DS,[SI.user_CS]
540
541Create_copy:
542 XOR SI,SI ; copy all 80h bytes
543 MOV DI,SI
544 MOV CX,80H
545 REP MOVSW
546
547 TEST BYTE PTR [CreatePDB],0FFh ; Shall we create a process?
548 JZ Create_PDB_cont ; nope, old style call
549;
550; Here we set up for a new process...
551;
552
553 PUSH CS
554 POP DS
555 ASSUME DS:DOSGROUP
556 XOR BX,BX ; dup all jfns
557 MOV CX,FilPerProc
558
559Create_dup_jfn:
560 PUSH ES ; save new PDB
561 invoke get_jfn_pointer ; ES:DI is jfn
562 JC create_skip ; not a valid jfn
563 PUSH ES ; save him
564 PUSH DI
565 invoke get_sf_from_jfn ; get sf pointer
566 JC create_no_inc
567 INC ES:[DI].sf_ref_count ; new fh
568
569create_no_inc:
570 POP DI
571 POP ES ; get old jfn
572 MOV AL,ES:[DI] ; get sfn
573 POP ES
574 PUSH ES
575 MOV AL,ES:[BX] ; copy into new place!
576
577create_skip:
578 POP ES
579 INC BX ; next jfn...
580 LOOP create_dup_jfn
581
582 PUSH [CurrentPDB] ; get current process
583 POP BX
584 PUSH BX
585 POP ES:[PDB_Parent_PID] ; stash in child
586 MOV [CurrentPDB],ES
587 ASSUME DS:NOTHING
588 MOV DS,BX
589;
590; end of new process create
591;
592Create_PDB_cont:
593 MOV BYTE PTR [CreatePDB],0h ; reset flag
594 MOV AX,DS:[2] ; set up size for fall through
595
596entry SETMEM
597ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
598
599; Inputs:
600; AX = Size of memory in paragraphs
601; DX = Segment
602; Function:
603; Completely prepares a program base at the
604; specified segment.
605; Called at DOS init
606; Outputs:
607; DS = DX
608; ES = DX
609; [0] has INT int_abort
610; [2] = First unavailable segment ([ENDMEM])
611; [5] to [9] form a long call to the entry point
612; [10] to [13] have exit address (from int_terminate)
613; [14] to [17] have ctrl-C exit address (from int_ctrl_c)
614; [18] to [21] have fatal error address (from int_fatal_abort)
615; DX,BP unchanged. All other registers destroyed.
616
617 XOR CX,CX
618 MOV DS,CX
619 MOV ES,DX
620 MOV SI,addr_int_terminate
621 MOV DI,SAVEXIT
622 MOV CX,6
623 REP MOVSW
624 MOV ES:[2],AX
625 SUB AX,DX
626 CMP AX,MAXDIF
627 JBE HAVDIF
628 MOV AX,MAXDIF
629HAVDIF:
630 MOV BX,ENTRYPOINTSEG
631 SUB BX,AX
632 MOV CL,4
633 SHL AX,CL
634 MOV DS,DX
635 MOV WORD PTR DS:[PDB_CPM_Call+1],AX
636 MOV WORD PTR DS:[PDB_CPM_Call+3],BX
637 MOV DS:[PDB_Exit_Call],(int_abort SHL 8) + mi_INT
638 MOV BYTE PTR DS:[PDB_CPM_Call],mi_Long_CALL
639 MOV WORD PTR DS:[PDB_Call_System],(int_command SHL 8) + mi_INT
640 MOV BYTE PTR DS:[PDB_Call_System+2],mi_Long_RET
641 return
642
643$CREATE_PROCESS_DATA_BLOCK ENDP
644 do_ext
645
646 CODE ENDS
647 END
648