summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FORMAT/FOREXEC.ASM
blob: 46026cb2329de8d813f629e59ce5ccd24103557b (plain) (blame)
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
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
page	,132					;
;

;*****************************************************************************
;*****************************************************************************
;UTILITY NAME: FORMAT.COM
;
;MODULE NAME: FOREXEC.SAL
;
;
;
; ��������������Ŀ
; �EXEC_FS_FORMAT�
; ����������������
;   �
;   �������Ŀ
;   ôShrink�
;   ���������
;   �����������Ŀ
;   ôSetup_EXEC�
;   �������������
;   ����������Ŀ	  ������������Ŀ
;   ôEXEC_ArgV����������ĴEXEC_Program�
;   ������������	  ��������������
;   �������������������Ŀ ������������Ŀ
;   ôEXEC_Cur_Directory�ĴEXEC_Program�
;   ��������������������� ��������������
;   �������������Ŀ	  �������������������Ŀ ������������Ŀ
;   ��EXEC_Routine�������ĴBuild_Path_And_EXEC�ĴEXEC_Program�
;    ��������������	  ��������������������� ��������������
;
; Change List: AN000 - New code DOS 3.3 spec additions
;	       AC000 - Changed code DOS 3.3 spec additions
;*****************************************************************************
;*****************************************************************************

title	DOS	3.30 FORMAT EXEC Module

IF1
	%OUT	ASSEMBLING: DOS 3.3 FORMAT EXEC LOADER
	%OUT
ENDIF

code	segment public para 'code'
	assume	cs:code
code	ends

;
;*****************************************************************************
; Include files
;*****************************************************************************
;

.xlist
INCLUDE FORCHNG.INC
INCLUDE FORMACRO.INC
INCLUDE SYSCALL.INC
INCLUDE FOREQU.INC
.list

;
;*****************************************************************************
; Public Data
;*****************************************************************************
;

	Public	Drive_Letter_Msg

;
;*****************************************************************************
; Public Routines
;*****************************************************************************
;


IF FSExec					;an018; dms;if /FS: desired

	Public	EXEC_FS_Format

ENDIF		;FSExec 			;an018; dms;end /FS: conditional

	Extrn	GetFSiz:near


;
;*****************************************************************************
; External Data Declarations
;*****************************************************************************
;

	extrn	ExitStatus:Byte
	extrn	Fatal_Error:Byte
	extrn	FS_String_Buffer:Byte
	extrn	msgEXECFailure:Byte
	extrn	PSP_Segment:Word
	extrn	drive:byte

;
;****************************************************************************
; Structures
;****************************************************************************
;


Exec_Block_Parms struc
Segment_Env dw	0
Offset_Command dw 0
Segment_Command dw 0
Offset_FCB1 dw	0
Segment_FCB1 dw 0
Offset_FCB2 dw	0
Segment_FCB2 dw 0

Exec_Block_Parms ends


;
;****************************************************************************
; Equates
;****************************************************************************
;


String_Done	equ	0
No_Error	equ	0
Error		equ	1
Stderr		equ	2
Stack_Space	equ	02eh							;an000; dms; IBM addition ROM paras

;
;****************************************************************************
; PSP Area
;****************************************************************************
;

PSP	segment public	para   'DUMMY'

org	2Ch
PSP_ENV_SEGMENT label word

FCB1	equ	5Ch

FCB2	equ	6Ch

org	80h
Command_Line label byte


PSP	ends

;
;****************************************************************************
; Data Area
;****************************************************************************
;

data	segment public para 'DATA'
	assume	ds:data,es:nothing

Exec_Block Exec_Block_Parms <>
EXEC_Path db	66 dup(0)

Drive_Letter_Msg db "A:",0			;Drive for exec fail message

SP_Save 	dw	?			;an000; dms;
SS_Save 	dw	?			;an000; dms;


;These next two should stay togather
; ---------------------------------------
						;
Path_String db	"PATH=" 			;				;AN000;
Len_Path_String equ $ - Path_String		;				;AN000;
						;
;----------------------------------------




;These should stay togather
; ---------------------------------------
						;
Search_FORMAT db "FORMAT"			;				;AC000;
Len_Search_FORMAT equ $ - Search_FORMAT 	;				;     ;
Search_Format_End equ $
						;				;     ;
;----------------------------------------


;These next two should stay togather
; ---------------------------------------





data	ends

code	segment public para 'code'
	assume	cs:code,ds:data

;
;****************************************************************************
; Main Routine
;****************************************************************************
;
;
;
;
;

IF FSExec					;an018; dms;if /FS: desired


Procedure Exec_FS_Format			;				;AC000;

	Set_Data_Segment			;
	call	Set_FCB1_Drive			;an000;dms;
	call	Shrink				;				;     ;
	mov	al,ExitStatus			;Setblock fail? 		;AC000;
	cmp	al,Error			; "  "	  "  "			;     ;
;	$IF	NE				;Nah, keep crusin!		;AN000;
	JE $$IF1
	   call    Setup_Exec			;				;     ;
	   call    Exec_Argv			;try exec from dir BASIC loaded ;     ;
	   mov	   al,ExitStatus		;				;AC000;
	   cmp	   al,Error			;				;     ;
;	   $IF	   E,AND			;				;AC000;
	   JNE $$IF2
	   call    Exec_Cur_Directory		;				;     ;
	   mov	   al,ExitStatus		;Try exec from cur directory	;AC000;
	   cmp	   al,Error			;				;     ;
;	   $IF	   E,AND			;				;AC000;
	   JNE $$IF2
	   call    EXEC_Routine 		;				;     ;
	   mov	   al,ExitStatus		;				;AC000;
	   cmp	   al,Error			;				;     ;
;	   $IF	   E				;				;AC000;
	   JNE $$IF2
  ;	      mov     bl,FCB1			;Get target drive from FCB
  ;	      mov     bl,Drive			;an000;dms;
	      push    ds			;an000;dms;save ds
	      push    si			;an000;dms;save si
	      mov     si,PSP_Segment		;an000;dms;get psp
	      mov     ds,si			;an000;dms;put psp in ds
	      assume  ds:PSP			;an000;dms;

	      mov     si,FCB1			;an000;dms;ptr to 1st. FCB
	      mov     bl,byte ptr ds:[si]	;an000;dms;get drive ID

	      pop     si			;an000;dms;restore si
	      pop     ds			;an000;dms;restore ds
	      Set_Data_Segment			;an000;dms;set segments

	      cmp     bl,0			;Is it default drive?		;AN000;
;	      $IF     E 			;Yes, turn it into drive letter ;AN000;
	      JNE $$IF3
		 push	 ax			;Save exit code 		;AN000;
		 DOS_Call Get_Default_Drive	;Get the default drive		;AN000;
		 add	 al,"A" 		;Turn into drive letter 	;AN000;
		 mov	 Drive_Letter_Msg,al	;Save it in message		;AN000;
		 pop	 ax			;Get return code back		;AN000;
;	      $ELSE				;Not default, A=1		;AN000;
	      JMP SHORT $$EN3
$$IF3:
		 add	 bl,"A"-1		;Convert to drive letter	;AN000;
		 mov	 Drive_Letter_Msg,bl	;				;AN000;
;	      $ENDIF				;AN000;
$$EN3:
	      Message msgEXECFailure		;				;AC000;
;	   $ELSE				;				;AN000;
	   JMP SHORT $$EN2
$$IF2:
	      DOS_Call WaitProcess		;				;AC000;
	      mov     ExitStatus,al		;				;     ;
;	   $ENDIF				;				;AN000;
$$EN2:
;	$ENDIF
$$IF1:
	mov	Fatal_Error,YES 		;Not really, indicates FS used	;AN000;
	ret					;				;     ;

Exec_FS_Format endp


;
;****************************************************************************
; Shrink
;****************************************************************************
;
;
;
;


Procedure Shrink				;				;AC000;

	mov	ax,cs				;an000; dms;get code segment
	mov	bx,ds				;an000; dms;get data segment
	sub	ax,bx				;an000; dms;data seg size
	mov	bx,ax				;an000; dms;save paras
	mov	ax,offset End_Program		;Get the offset of end of loader;     ;
	mov	cl,4				;Div by 16 to get para's        ;     ;
	shr	ax,cl				;				;     ;
	add	bx,ax				;an000; dms;add in code space
	add	bx,Stack_Space			;an000; dms;adjust for stack
	add	bx,11h				;an000; dms;give PSP space
	mov	ax,PSP_Segment
	mov	es,ax
	assume	es:nothing

	DOS_Call SetBlock			;				;AC000;
;	$IF	C				;If didn't work, quit           ;AC000;
	JNC $$IF9
		Message msgEXECFailure		     ;				     ;	   ;
		mov	ExitStatus,Error	     ;Bad stuff, time to quit	     ;AN000;
;	$ENDIF					;				;AN000;
$$IF9:
	ret					;				;     ;

Shrink	endp					;				;AN000;


;
;****************************************************************************
; Setup_Exec
;****************************************************************************
;
;
;
;

Procedure Setup_Exec				;				;AC000;

	Set_Data_Segment
	mov	ax,PSP_Segment			;Get segment of PSP		;AN000;
	mov	ds,ax				;  "  "    "  " 		;AN000;
						;     ;
	assume	ds:PSP
						;Setup dword pointer to command line to be passed

	mov	es:Exec_Block.Segment_Command,ax ;Segment for command line	 ;     ;
	mov	es:Exec_Block.Offset_Command,offset ds:Command_Line ;		      ;     ;

						;Setup dword pointer to first FCB to be passed

	mov	es:Exec_Block.Segment_FCB1,ax	;Segment for FCB1		;     ;
	mov	es:Exec_Block.Offset_FCB1,offset ds:FCB1 ;Offset of FCB at 05Ch       ;     ;

						;Setup dword pointer to second FCB to be passed 			    ;	  ;

	mov	es:Exec_Block.Segment_FCB2,ax	;Segment for FCB2		;     ;
	mov	es:Exec_Block.Offset_FCB2,offset ds:FCB2 ;Offset of FCB at 06Ch       ;     ;

						;Setup segment of Environment string, get from PSP			    ;	  ;

	mov	ax,ds:PSP_Env_Segment		;				;     ;
	mov	es:Exec_Block.Segment_Env,ax	;				;     ;
	Set_Data_Segment
	ret					;				;     ;


Setup_EXEC endp 				;				;AN000;

;
;****************************************************************************
; Exec_Argv
;****************************************************************************
;
; Read the environment to get the Argv(0) string, which contains the drive,
; path and filename that was loaded for FORMAT.COM. This will be used to find
; the xxxxxfmt.exe, assuming that it is in the same location or path as
; FORMAT.COM
;

Procedure EXEC_Argv				;				;AC000;

	Set_Data_Segment			;DS,ES = DATA
	cld					;				;     ;
	mov	ax,Exec_Block.Segment_Env	;Get the environment		;     ;
	mov	ds,ax				;Get addressability		;     ;

	assume	ds:nothing

	xor	si,si				;Start at beginning		;     ;
;	$DO					;Find argv(0) location		;AN000;
$$DO11:
;	   $DO					;Look for 0			;AN000;
$$DO12:
	      inc     si			;Get character			;     ;
	      cmp     byte ptr [si-1],0 	;Find string seperator? 	;     ;
;	   $ENDDO  E				;Yep				;AC000;
	   JNE $$DO12
	   inc	   si				;Get next char			;     ;
	   cmp	   byte ptr [si-1],0		;Are we at Argv(0)? (00?)	;     ;
;	$ENDDO	E				;Yes if we found double 0's     ;AC000;
	JNE $$DO11
	add	si,2				;Skip the word count		;     ;
	mov	di,si				;Save where string starts	;     ;
;	$DO					;Find length of Argv(0) string	;AN000;
$$DO15:
	   inc	   si				;Get char			;     ;
	   cmp	   byte ptr [si-1],0		;Is it the end? 		;     ;
;	$ENDDO	E				;End found if 0 found		;AC000;
	JNE $$DO15
	mov	cx,si				;Get number of bytes in string	;     ;
	sub	cx,di				;Put in cx reg for rep count	;     ;
	mov	si,di				;Point to path			;     ;
	mov	di,offset es:EXEC_Path		;Point to where to put it	;     ;
	rep	movsb				;Move the string		;     ;
	Set_Data_Segment			;				;AN000'
	dec	di				;Point at end of ArgV string	;     ;
	std					;Look backwards 		;AN000;
;	$DO					;Find 'FORMAT' in ARGV string	;AC000;
$$DO17:
	   mov	   cx,Len_Search_FORMAT 	;Get length to compare		;AC000;
	   mov	   si,offset Search_FORMAT_End-1 ;Look at comp string from end	 ;AC000;
	   repe    cmpsb			;See if same string		;AC000;
;	$ENDDO	E				;				;AC000;
	JNE $$DO17
	mov	si,offset FS_String_Buffer	;				;AN000;
	inc	di				;DI = replacement point-1	;AC000;
	cld					;Set direction flag back	;AN000;
	mov	cx,Len_FS_String_Buffer 	;Length of string to move	;AN000;
	rep	movsb				;Build part of the path 	;     ;
	call	EXEC_Program			;				;     ;
	ret					;				;     ;

EXEC_ArgV endp					;				;AN000;

;
;****************************************************************************
; EXEC_Program
;****************************************************************************
;
;
;
;

Procedure EXEC_Program				;				;AC000;

	Set_Data_Segment			;				;AN000;
	mov	ExitStatus,No_Error		;Setup to Exec the file 	;     ;
	mov	dx,offset Exec_Path		;				;     ;
	mov	bx,offset Exec_Block		;				;     ;
	mov	al,0				;				;     ;
	mov	word ptr SP_Save,sp		;an000; dms;save sp
	mov	word ptr SS_Save,ss		;an000; dms;save ss

	DOS_Call Exec				;				;AC000;

	cli					;an000; dms;turn off int's
	mov	sp,word ptr SP_Save		;an000; dms;retrieve sp
	mov	ss,word ptr SS_Save		;an000; dms;retrieve ss
	sti					;an000; dms;turn on int's


;	$IF	C				;CY means failure		;AC000;
	JNC $$IF19
	   mov	   ExitStatus,Error		;Set error code 		;     ;
;	$ENDIF					;				;AN000;
$$IF19:
	ret					;				;     ;

EXEC_Program endp				;				;AN000;


;
;****************************************************************************
; EXEC_Routine
;****************************************************************************
;
;
;
;

Procedure EXEC_Routine				;				;AN000;

	Set_Data_Segment			;				;AN000;
	mov	ExitStatus,Error		;Assume the worst		;     ;
	cld					;				;     ;
	push	ds				;				;     ;
	mov	ax,Exec_Block.Segment_Env	;Get the environment		;     ;
	mov	ds,ax				;Get addressability		;     ;
	assume	ds:nothing			;

	xor	si,si				;Start at beginning		;     ;
;	$SEARCH 				;				;AC000;
$$DO21:
	   cmp	   word ptr ds:[si],0		;End of the Evironment? 	;     ;
;	$EXITIF E				;Reached end, no more look	;AC000;
	JNE $$IF21
						;				;     ;
;	$ORELSE 				;Look for 'PATH=' in environment;AN000;
	JMP SHORT $$SR21
$$IF21:
	   mov	   di,offset Path_String	;  "  "    "  " 		;AC000;
	   mov	   cx,Len_Path_String		;  "  "    "  " 		;AC000;
	   repe    cmpsb			;  "  "    "  " 		;AC000;
;	$LEAVE	E				;Found if EQ			;AC000;
	JE $$EN21
;	$ENDLOOP				;Found PATH in environment	;AC000;
	JMP SHORT $$DO21
$$EN21:
	   call    Build_Path_And_Exec		;				;AN000;
;	$ENDSRCH				;				;     ;
$$SR21:
	pop	ds				;				;     ;
	ret					;				;     ;

EXEC_Routine endp

;
;****************************************************************************
; Build_Path_For_EXEC
;****************************************************************************
;
;
;
;

Procedure Build_Path_And_Exec			;				;AN000;

;	$DO					;				;AC000;
$$DO27:
	   cmp	   byte ptr ds:[si],0		;All path entries done? 	;     ;
;	   $IF	   NE				;				;AC000;
	   JE $$IF28
	      mov     di,offset EXEC_Path	;Point at where to put path	;     ;
	      mov     byte ptr es:[di],0	;End path just in case		;     ;
;	      $DO				;				;AC000;
$$DO29:
		 cmp	 byte ptr ds:[si],0	;End of Path?			;     ;
;	      $LEAVE  E 			;				;AC000;
	      JE $$EN29
		 cmp	 byte ptr ds:[si],';'	;End of entry?		       ;     ;
;		 $if	 e			;yes				;an000; dms;
		 JNE $$IF31
			 inc	si		;point to next character	;an000; dms;
			 jmp	EXIT_BPE_LOOP	;exit loop			;an000; dms;
;		 $endif 			;				;an000; dms;
$$IF31:
		 movsb				;Put char in path string	;     ;
;	      $ENDDO				;				;AN000;
	      JMP SHORT $$DO29
$$EN29:

EXIT_BPE_LOOP:					;				;an000; dms;
						;Path filled in,get backslash	;     ;
	      cmp     byte ptr ds:[si-1],0	;Any path there?		;     ;
;	      $IF     NE			;				;AC000;
	      JE $$IF34
						;Nope				;     ;
		 cmp	 byte ptr ds:[si-1],"\" ;Need a backslash?	     ;	   ;
;		 $IF	 NE			;				;AC000;
		 JE $$IF35
		    mov     byte ptr es:[di],"\" ;Yes, put one in	     ;	   ;
		    inc     di			;Line it up for next stuff	;     ;
		    inc     si			;				;     ;
;		 $ENDIF 			;				;AN000;
$$IF35:
		 push	 si			;Save place in path
		 push	 ds			;Save segment for environment	;AN000;
		 push	 es			;Xchange ds/es			;an000; dms;
		 pop	 ds			;				;an000; dms;
		 mov	 si,offset FS_String_Buffer ;Fill in filename		    ;	  ;
		 mov	 cx, Len_FS_String_Buffer ;				  ;	;
		 rep	 movsb			;				;     ;
		 call	 Exec_Program		;				;     ;
		 cmp	 ExitStatus,No_Error	;E if EXEC okay 		;AN000;
		 pop	 ds			;Get Env segment back		;     ;
		 pop	 si			;Get place in path back
;	      $ENDIF				;E if all paths done		;AN000;
$$IF34:
;	   $ENDIF				;E if all paths done		;AN000;
$$IF28:
;	$ENDDO	E				;Exit if E			;AN000;
	JNE $$DO27
	ret					;				;AN000;

Build_Path_And_EXEC Endp			;				;AN000;



;
;****************************************************************************
; Exec_Cur_Directory
;****************************************************************************
;
;
;
;

Procedure Exec_Cur_Directory			;				;AC000;

	Set_Data_Segment			;				;AN000;
	mov	si,offset FS_String_Buffer	;Setup path for current dir	;     ;
	mov	di,offset EXEC_Path		;				;     ;
	mov	cx,Len_FS_String_Buffer 	;				;     ;
	rep	movsb				;				;     ;
	call	EXEC_Program			;				;     ;
	ret					;				;     ;

EXEC_Cur_Directory endp 			;				;AN000;

;=========================================================================
; Set_FCB1_Drive	: This routine sets the 1st. byte of the FCB1,
;			  the drive identifier, to the default drive.
;=========================================================================

Procedure Set_FCB1_Drive			;an000;dms;set drive ID

	push	ds				;an000;dms;save ds
	push	si				;an000;dms;save si

	mov	si,PSP_Segment			;an000;dms;get segment of PSP
	mov	ds,si				;an000;dms;put it in ds
	assume	ds:PSP				;an000;dms;
	mov	si,FCB1 			;an000;dms;ptr to FCB1
	mov	byte ptr ds:[si],00h		;an000;dms;set drive ID to
						;      default drive
	pop	si				;an000;dms;restore si
	pop	ds				;an000;dms;restore ds
	Set_Data_Segment			;an000;dms;set up segmentation
	ret					;an000;dms;

Set_FCB1_Drive	endp				;an000;dms;

ENDIF		;FSExec 			;an018; dms;end /FS: conditional
						;	    assembly

public End_Program
End_Program label byte

code	ends
	end