]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/ATTRIB/ATTRIBA.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / CMD / ATTRIB / ATTRIBA.ASM
1 page ,132 ;\ f
2 title New_C.C - DOS entry to the KWC's 'C' programs
3
4 ;
5 ; This module has been modified extensively for my personal
6 ; use.
7 ;
8 ; name XCMAIN -- initiate execution of C program
9 ;
10 ; description This is the main module for a C program on the
11 ; DOS implementation. It initializes the segment
12 ; registers, sets up the stack, and calls the C main
13 ; function _main with a pointer to the remainder of
14 ; the command line.
15 ;
16 ; Also defined in this module is the exit entry point
17 ; XCEXIT.
18 ;
19 ; $salut (4,12,18,41)
20 SETBLOCK EQU 4AH ;MODIFY ALLOCATED MEMORY BLOCKS
21 ;ES = SEGMENT OF THE BLOCK
22 ;BX = NEW REQUESTED BLOCK SIZE
23 ; IN PARAGRAPHS
24 ;OUTPUT: BX=MAX SIZE POSSIBLE IF CY SET
25 ;AX = ERROR CODE IF CY SET
26
27 RET_CD_EXIT EQU 4CH ;EXIT TO DOS, PASSING RETURN CODE
28 ;AL=RETURN CODE
29
30 RET_EXIT equ 4ch ;AN000; ;terminate
31 ABORT equ 2 ;AN000; ;if >=, retry
32 XABORT equ 1 ;AN000; ;errorlevel return in al
33
34
35 extrn _inmain:near ;AC000;
36 extrn _Reset_appendx:near ;AN000;
37 extrn _old_int24_off:dword ;AN000;
38
39
40 psp segment at 0 ;<--emk
41 psp_ret dw ? ;int 20h
42 psp_memsz dw ? ;memory size
43 org 2ch
44 psp_env dw ? ;segid of environment
45 org 80h
46 psp_parlen db ? ;length of DOS command line parms
47 psp_par db 127 dup(?) ;DOS command line parms
48 psp ends
49 page
50
51 ;
52 ; The following segment serves only to force "pgroup" lower in
53 ; memory.
54 ;
55
56 base segment PARA PUBLIC 'DATA'
57
58 db 00dh,00ah
59 db "----------\x0d\x0a"
60 db " DOS ATTRIB function \x0d\x0a"
61 db "--------------------\x0d\x0a"
62 db 00dh,00ah,01ah
63
64 base ends
65
66
67 ;
68 ; The data segment defines locations which contain the offsets
69 ; of the base and top of the stack.
70 ;
71
72 _data segment PARA public 'DATA'
73
74 irp name,<_top,_base,_cs,_ss,_psp,_env,_rax,_rbx,_rcx,_rdx,_rds,_rsi,_rbp,_res,_rdi>
75 public name
76 name dw 0
77 endm
78
79 _data ends
80
81 ;
82 ; The stack segment is included to prevent the warning from the
83 ; linker, and also to define the base (lowest address) of the stack.
84 ;
85
86 stack segment PARA stack 'data'
87
88 SBase dw 128 dup (?)
89
90 stack ends
91
92 null segment para public 'BEGDATA'
93 null ends
94 const segment word public 'CONST'
95 const ends
96 _bss segment word public 'BSS'
97 _bss ends
98 pgroup group base,_text
99 dgroup group null, _data, const, _bss, stack
100
101 page
102
103 ;
104 ; The main program must set up the initial segment registers
105 ; and the stack pointer, and set up a far return to the DOS
106 ; exit point at ES:0. The command line bytes from the program
107 ; segment prefix are moved onto the stack, and a pointer to
108 ; them supplied to the C main module _main (which calls main).
109 ;
110
111 _text segment PARA public 'CODE'
112
113 public XCMAIN
114
115 assume cs:pgroup
116 assume ds:psp ;<--emk
117 assume es:psp ;<--emk
118 assume ss:stack ;<--emk
119
120 XCMAIN proc far
121
122 mov ax,dgroup
123 mov ds,ax ;initialize ds and ss
124 assume ds:dgroup
125
126 mov bx,psp_memsz ;total memory size (paragraphs)
127 sub bx,ax
128 test bx,0f000h
129 ; $IF Z ;branch if more than or equal 64K bytes
130 JNZ $$IF1
131
132 mov cl,4
133 shl bx,cl ;highest available byte
134 ; $ELSE
135 JMP SHORT $$EN1
136 $$IF1:
137 mov bx,0fff0h
138 ; $ENDIF
139 $$EN1:
140 cli ; disable interrupts while changing stack <---kwc
141 mov ss,ax ; set ss <---kwc
142 mov sp,bx ; set stack pointer <---kwc
143 sti ;enable interrupts
144 assume ss:DGroup ;<--emk
145
146 mov _ss,ss
147 mov _cs,cs
148 mov _top,bx ;save top of stack
149
150 mov ax,offset DGroup:SBase
151 mov _base,ax ;store ptr to bottom of stack
152
153 ; code added here to allow allocates and exec's in the c code
154 ; we will have to calculate the size of the code that has been loaded
155
156 mov bx,sp ; bx = length of the stack
157 shr bx,1
158 shr bx,1
159 shr bx,1
160 shr bx,1 ; bx = number of paragraphs in stack,
161 add bx,1 ; (fudge factor!)<--emk ,was 10
162 mov ax,ss
163 add bx,ax ; bx = paragraph a little past the stack
164 mov ax,es ; ax = paragraph of the psp
165 sub bx,ax ; bx = number of paragraphs in code
166 mov ah,setblock
167 int 021h
168
169 ; end of added code!
170
171 mov _psp,es ; save pointer to psp for setblock <---kwc
172 mov cl,psp_parlen ;get number of bytes <--emk
173 xor ch,ch ;cx = number of bytes of parms!
174 mov si,offset psp_par ;point to DOS command line parms <--emk
175
176 ; more modified code, picking up argv[0] from the environment!
177
178 mov ds,psp_env ;set ds to segid of environment from es:psp
179 assume ds:nothing
180
181 mov _env,ds ;remember where environment is
182
183 mov si,0 ;clear index to step thru env
184 ;The env has a set of keyword=operand, each one ending with a single null byte.
185 ;At the end of the last one is a double null. We are looking for the end of
186 ;all these keywords, by looking for the double null.
187 ; $DO COMPLEX
188 JMP SHORT $$SD4
189 $$DO4:
190 inc si ;bump index to look at next byte in env
191 ; $STRTDO
192 $$SD4:
193 cmp word ptr [si],0 ;is this a double null delimiter?
194 ; $ENDDO E ;ifdouble null found, exit
195 JNE $$DO4
196 ;At end of env is the double null and a word counter
197 add si,4 ;step over this double null delimiter
198 ; and the following word counter
199 push si ;save pointer to next field in env
200 ;This is the invocation statement, including the path name, even if not specified
201 ;but supplied by PATH.
202
203 ;continue stepping thru env looking for one more null byte, which indicates
204 ;the end of the invocation command.
205 ; $DO
206 $$DO7:
207 lodsb ;get a byte from env to al
208 cmp al,0 ;is this a null byte?
209 ; $ENDDO E ;quit if null is found
210 JNE $$DO7
211
212 mov bx,si ; bx -> asciiz zero
213 pop si ; si -> first byte of agrv[0], the invocation command
214 sub bx,si ; bx = length of argv[0]
215 mov dx,bx ; (save for the copy later)
216 dec dx
217 add bx,cx ; add in the length of the rest of the parms
218 inc bx ; add one for the asciiz zero!
219 and bx,0fffeh ;force even number of bytes
220 add bx,2 ;adjust for possible rounding error
221 sub sp,bx ;allocate space on stack
222 mov di,sp ; (es:di) -> where we will put the stuff
223 push es
224 mov ax,ss
225 mov es,ax
226 xchg cx,dx ; length of argv[0] to copy, save length of parms
227 rep movsb ; (ds:si) already point to argv[0]
228 pop es
229 mov ss:byte ptr [di],' ' ;store trailing blank!
230 inc di
231 mov _rdi,di ;AN000; save start of command parms
232 xchg cx,dx ; restore length of parms
233 ; $IF NCXZ ;if some bytes to move,
234 JCXZ $$IF9
235
236 mov si,offset psp_par ;point to DOS command line parms in psp
237 ; $DO
238 $$DO10:
239 mov al,es:[si] ;move bytes to stack
240 mov ss:[di],al
241 inc si
242 inc di
243 ; $ENDDO LOOP
244 LOOP $$DO10
245 ; $ENDIF ;bytes to move?
246 $$IF9:
247 xor ax,ax
248 mov ss:[di],al ;store null byte
249 mov ax,ss
250 mov ds,ax ;es, ds, and ss are all equal
251 assume ds:DGroup
252
253 mov es,ax ;es, ds, and ss are all equal
254 assume es:DGroup
255
256 mov ax,_rdi ;AN000; restore offset of parms on stack
257 push ax ;ptr to command line
258
259 call _inmain ;AC000; call C main
260
261 mov ah,ret_cd_exit ;return to DOS
262 int 21h ;errorlevel ret code in al
263
264 XCMAIN endp
265
266 page
267
268 ;
269 ; name XCEXIT -- terminate execution of C program
270 ;
271 ; description This function terminates execution of the current
272 ; program by returning to DOS. The error code
273 ; argument normally supplied to XCEXIT is ignored
274 ; in this implementation.
275 ;
276 ; input - al = binary return code for dos/ERRORLEVEL
277 ;
278
279 assume cs:PGroup
280 assume ds:DGroup
281 assume es:DGroup
282 assume ss:DGroup
283
284 public xcexit
285 XCEXIT proc far
286
287 mov ah,ret_cd_exit ; <--- kwc
288 int 021h ; <--- kwc
289
290 XCEXIT endp
291
292 ;--------------------------------------------------------------------------
293
294 PAGE
295
296 CENTER MACRO NAMELIST
297 PUSH BP ; SAVE CURRENT BP
298 MOV BP,SP ; POINT AT STACK WITH BP
299 WORKOFS = 0
300 IRP ANAME,<NAMELIST> ; FOR EACH WORKING VARIABLE
301 IFNB <&ANAME>
302 WORKOFS = WORKOFS-2 ; WE WILL ALLOCATE ONE
303 DOEQU &ANAME,%WORKOFS ; WORD ON THE STACK THAT
304 ENDIF
305 ENDM ; IS UNDER SS,BP
306 ADD SP,WORKOFS
307 ENDM
308
309 DOEQU MACRO NAME,VALUE
310 &NAME EQU &VALUE
311 ENDM
312
313 CEXIT MACRO VALUE
314 MOV SP,BP
315 POP BP
316 RET
317 ENDM
318
319 PAGE
320
321 ; INPUT PARAMATERS PASSED ON STACK
322
323 PARMS STRUC
324
325 OLD_BP DW ? ; SAVED BP
326 RETADD DW ? ; RETURN ADDRESS
327 PARM_1 DW ?
328 PARM_2 DW ?
329 PARM_3 DW ?
330 PARM_4 DW ?
331 PARM_5 DW ?
332 PARM_6 DW ?
333 PARM_7 DW ?
334 PARM_8 DW ?
335
336 PARMS ENDS
337
338 SAVE_SS DW 0
339 SAVE_SP DW 0
340
341 PAGE
342
343 ;************************************************************************
344 ; ;
345 ; Subroutine Name: ;
346 ; getpspbyte ;
347 ; ;
348 ; Subroutine Function: ;
349 ; get a byte from PSP ; ;
350 ; ;
351 ; Input: ;
352 ; SS:[BP]+PARM1 = offset in PSP ;
353 ; ;
354 ; Output: ;
355 ; AL = byte from PSP:offset ;
356 ; ;
357 ; C calling convention: ;
358 ; char = getpspbyte(offset); ;
359 ; ;
360 ;************************************************************************
361
362 MOFFSET EQU PARM_1 ;AN000;
363
364 ASSUME CS:PGROUP ;AN000;
365 ASSUME DS:DGROUP ;AN000;
366 ASSUME ES:DGROUP ;AN000;
367 ASSUME SS:DGROUP ;AN000;
368
369 PUBLIC _GETPSPBYTE ;AN000;
370 _GETPSPBYTE PROC NEAR ;AN000;
371
372 CENTER ;AN000;
373
374 PUSH DS ;AN000;
375
376 MOV DS,_PSP ;AN000; get save PSP segment
377 MOV SI,[BP].MOFFSET ;AN000; get offset into PSP
378 LODSB ;AN000; get PSP byte
379 MOV AH,0 ;AN000; zero high byte
380
381 POP DS ;AN000;
382
383 CEXIT ;AN000;
384
385 _GETPSPBYTE ENDP
386
387
388 ;************************************************************************
389 ; ;
390 ; Subroutine Name: ;
391 ; putpspbyte ;
392 ; ;
393 ; Subroutine Function: ;
394 ; put a byte into PSP ; ;
395 ; ;
396 ; Input: ;
397 ; SS:[BP]+MVALUE = byte in AL ;
398 ; SS:[BP]+MOFFSET = offset in PSP ;
399 ; ;
400 ; Output: ;
401 ; none ;
402 ; ;
403 ; C calling convention: ;
404 ; putpspbyte(offset,char); ;
405 ; ;
406 ;************************************************************************
407
408
409 MVALUE EQU PARM_2 ;AN000;
410 MOFFSET EQU PARM_1 ;AN000;
411
412 ASSUME CS:PGROUP ;AN000;
413 ASSUME DS:DGROUP ;AN000;
414 ASSUME ES:DGROUP ;AN000;
415 ASSUME SS:DGROUP ;AN000;
416
417 PUBLIC _PUTPSPBYTE ;AN000;
418 _PUTPSPBYTE PROC NEAR ;AN000;
419
420 CENTER ;AN000;
421
422 PUSH ES ;AN000;
423
424 MOV AX,[BP].MVALUE ;AN000; get byte to store in PSP
425 MOV ES,_PSP ;AN000; get saved PSP segment
426 MOV DI,[BP].MOFFSET ;AN000; get offset in PSP
427 STOSB ;AN000; store the byte
428
429 POP ES ;AN000;
430
431 CEXIT ;AN000;
432
433 _PUTPSPBYTE ENDP
434
435
436 ;-------------------------------------------------------------------
437 ;
438 ; MODULE: crit_err_handler()
439 ;
440 ; PURPOSE: Supplies assembler exit routines for
441 ; critical error situations
442 ;
443 ; CALLING FORMAT:
444 ; crit_err_handler;
445 ;-------------------------------------------------------------------
446 public _crit_err_handler ;AN000;
447 public vector ;AN000;
448 vector dd 0 ;AN000;
449 ; ;AN000;
450 _crit_err_handler proc near ;AN000;
451 pushf ;AN000;
452 push ax ; save registers ;AN000;
453 push ds ;AN000;
454 mov ax,dgroup ;get C data segment ;AN000;
455 mov ds,ax ;AN000;
456 mov ax,word ptr ds:_old_int24_off ;get int24 offset ;AN000;
457 mov word ptr cs:vector,ax ;AN000;
458 mov ax,word ptr ds:_old_int24_off+2 ;get int24 segment ;AN000;
459 mov word ptr cs:vector+2,ax ;AN000;
460 pop ds ;restore registers ;AN000;
461 pop ax ;AN000;
462 ; ;AN000;
463 call dword ptr cs:vector ; invoke DOS err hndlr ;AN000;
464 cmp al,ABORT ; what was the user's response ;AN000;
465 jnge retry ; ;AN000;
466 ; ;AN000;
467 mov ax,dgroup ;get C data segment ;AN000;
468 mov ds,ax ;AN000;
469 mov es,ax ;AN000;
470 call _Reset_appendx ; restore user's orig append/x ;AN000;
471 ; ;AN000;
472 mov ax,(RET_EXIT shl 8)+XABORT ; return to DOS w/criterr error ;AN000;
473 int 21h ; ;AN000;
474 retry: ;AN000;
475 iret ;AN000;
476 ; ;AN000;
477 _crit_err_handler endp ;AN000;
478 _text ends ;AN000;
479 end XCMAIN ;AN000;
480 \1a