From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/ATTRIB/ATTRIBA.ASM | 480 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 v4.0/src/CMD/ATTRIB/ATTRIBA.ASM (limited to 'v4.0/src/CMD/ATTRIB/ATTRIBA.ASM') diff --git a/v4.0/src/CMD/ATTRIB/ATTRIBA.ASM b/v4.0/src/CMD/ATTRIB/ATTRIBA.ASM new file mode 100644 index 0000000..4f9c312 --- /dev/null +++ b/v4.0/src/CMD/ATTRIB/ATTRIBA.ASM @@ -0,0 +1,480 @@ + page ,132 ; + title New_C.C - DOS entry to the KWC's 'C' programs + +; +; This module has been modified extensively for my personal +; use. +; +; name XCMAIN -- initiate execution of C program +; +; description This is the main module for a C program on the +; DOS implementation. It initializes the segment +; registers, sets up the stack, and calls the C main +; function _main with a pointer to the remainder of +; the command line. +; +; Also defined in this module is the exit entry point +; XCEXIT. +; +; $salut (4,12,18,41) +SETBLOCK EQU 4AH ;MODIFY ALLOCATED MEMORY BLOCKS + ;ES = SEGMENT OF THE BLOCK + ;BX = NEW REQUESTED BLOCK SIZE + ; IN PARAGRAPHS + ;OUTPUT: BX=MAX SIZE POSSIBLE IF CY SET + ;AX = ERROR CODE IF CY SET + +RET_CD_EXIT EQU 4CH ;EXIT TO DOS, PASSING RETURN CODE + ;AL=RETURN CODE + +RET_EXIT equ 4ch ;AN000; ;terminate +ABORT equ 2 ;AN000; ;if >=, retry +XABORT equ 1 ;AN000; ;errorlevel return in al + + + extrn _inmain:near ;AC000; + extrn _Reset_appendx:near ;AN000; + extrn _old_int24_off:dword ;AN000; + + +psp segment at 0 ;<--emk +psp_ret dw ? ;int 20h +psp_memsz dw ? ;memory size + org 2ch +psp_env dw ? ;segid of environment + org 80h +psp_parlen db ? ;length of DOS command line parms +psp_par db 127 dup(?) ;DOS command line parms +psp ends + page + +; +; The following segment serves only to force "pgroup" lower in +; memory. +; + +base segment PARA PUBLIC 'DATA' + + db 00dh,00ah + db "----------\x0d\x0a" + db " DOS ATTRIB function \x0d\x0a" + db "--------------------\x0d\x0a" + db 00dh,00ah,01ah + +base ends + + +; +; The data segment defines locations which contain the offsets +; of the base and top of the stack. +; + +_data segment PARA public 'DATA' + + irp name,<_top,_base,_cs,_ss,_psp,_env,_rax,_rbx,_rcx,_rdx,_rds,_rsi,_rbp,_res,_rdi> + public name +name dw 0 + endm + +_data ends + +; +; The stack segment is included to prevent the warning from the +; linker, and also to define the base (lowest address) of the stack. +; + +stack segment PARA stack 'data' + +SBase dw 128 dup (?) + +stack ends + +null segment para public 'BEGDATA' +null ends +const segment word public 'CONST' +const ends +_bss segment word public 'BSS' +_bss ends +pgroup group base,_text +dgroup group null, _data, const, _bss, stack + + page + +; +; The main program must set up the initial segment registers +; and the stack pointer, and set up a far return to the DOS +; exit point at ES:0. The command line bytes from the program +; segment prefix are moved onto the stack, and a pointer to +; them supplied to the C main module _main (which calls main). +; + +_text segment PARA public 'CODE' + + public XCMAIN + + assume cs:pgroup + assume ds:psp ;<--emk + assume es:psp ;<--emk + assume ss:stack ;<--emk + +XCMAIN proc far + + mov ax,dgroup + mov ds,ax ;initialize ds and ss + assume ds:dgroup + + mov bx,psp_memsz ;total memory size (paragraphs) + sub bx,ax + test bx,0f000h +; $IF Z ;branch if more than or equal 64K bytes + JNZ $$IF1 + + mov cl,4 + shl bx,cl ;highest available byte +; $ELSE + JMP SHORT $$EN1 +$$IF1: + mov bx,0fff0h +; $ENDIF +$$EN1: + cli ; disable interrupts while changing stack <---kwc + mov ss,ax ; set ss <---kwc + mov sp,bx ; set stack pointer <---kwc + sti ;enable interrupts + assume ss:DGroup ;<--emk + + mov _ss,ss + mov _cs,cs + mov _top,bx ;save top of stack + + mov ax,offset DGroup:SBase + mov _base,ax ;store ptr to bottom of stack + +; code added here to allow allocates and exec's in the c code +; we will have to calculate the size of the code that has been loaded + + mov bx,sp ; bx = length of the stack + shr bx,1 + shr bx,1 + shr bx,1 + shr bx,1 ; bx = number of paragraphs in stack, + add bx,1 ; (fudge factor!)<--emk ,was 10 + mov ax,ss + add bx,ax ; bx = paragraph a little past the stack + mov ax,es ; ax = paragraph of the psp + sub bx,ax ; bx = number of paragraphs in code + mov ah,setblock + int 021h + +; end of added code! + + mov _psp,es ; save pointer to psp for setblock <---kwc + mov cl,psp_parlen ;get number of bytes <--emk + xor ch,ch ;cx = number of bytes of parms! + mov si,offset psp_par ;point to DOS command line parms <--emk + +; more modified code, picking up argv[0] from the environment! + + mov ds,psp_env ;set ds to segid of environment from es:psp + assume ds:nothing + + mov _env,ds ;remember where environment is + + mov si,0 ;clear index to step thru env +;The env has a set of keyword=operand, each one ending with a single null byte. +;At the end of the last one is a double null. We are looking for the end of +;all these keywords, by looking for the double null. +; $DO COMPLEX + JMP SHORT $$SD4 +$$DO4: + inc si ;bump index to look at next byte in env +; $STRTDO +$$SD4: + cmp word ptr [si],0 ;is this a double null delimiter? +; $ENDDO E ;ifdouble null found, exit + JNE $$DO4 +;At end of env is the double null and a word counter + add si,4 ;step over this double null delimiter + ; and the following word counter + push si ;save pointer to next field in env +;This is the invocation statement, including the path name, even if not specified +;but supplied by PATH. + +;continue stepping thru env looking for one more null byte, which indicates +;the end of the invocation command. +; $DO +$$DO7: + lodsb ;get a byte from env to al + cmp al,0 ;is this a null byte? +; $ENDDO E ;quit if null is found + JNE $$DO7 + + mov bx,si ; bx -> asciiz zero + pop si ; si -> first byte of agrv[0], the invocation command + sub bx,si ; bx = length of argv[0] + mov dx,bx ; (save for the copy later) + dec dx + add bx,cx ; add in the length of the rest of the parms + inc bx ; add one for the asciiz zero! + and bx,0fffeh ;force even number of bytes + add bx,2 ;adjust for possible rounding error + sub sp,bx ;allocate space on stack + mov di,sp ; (es:di) -> where we will put the stuff + push es + mov ax,ss + mov es,ax + xchg cx,dx ; length of argv[0] to copy, save length of parms + rep movsb ; (ds:si) already point to argv[0] + pop es + mov ss:byte ptr [di],' ' ;store trailing blank! + inc di + mov _rdi,di ;AN000; save start of command parms + xchg cx,dx ; restore length of parms +; $IF NCXZ ;if some bytes to move, + JCXZ $$IF9 + + mov si,offset psp_par ;point to DOS command line parms in psp +; $DO +$$DO10: + mov al,es:[si] ;move bytes to stack + mov ss:[di],al + inc si + inc di +; $ENDDO LOOP + LOOP $$DO10 +; $ENDIF ;bytes to move? +$$IF9: + xor ax,ax + mov ss:[di],al ;store null byte + mov ax,ss + mov ds,ax ;es, ds, and ss are all equal + assume ds:DGroup + + mov es,ax ;es, ds, and ss are all equal + assume es:DGroup + + mov ax,_rdi ;AN000; restore offset of parms on stack + push ax ;ptr to command line + + call _inmain ;AC000; call C main + + mov ah,ret_cd_exit ;return to DOS + int 21h ;errorlevel ret code in al + +XCMAIN endp + + page + +; +; name XCEXIT -- terminate execution of C program +; +; description This function terminates execution of the current +; program by returning to DOS. The error code +; argument normally supplied to XCEXIT is ignored +; in this implementation. +; +; input - al = binary return code for dos/ERRORLEVEL +; + + assume cs:PGroup + assume ds:DGroup + assume es:DGroup + assume ss:DGroup + + public xcexit +XCEXIT proc far + + mov ah,ret_cd_exit ; <--- kwc + int 021h ; <--- kwc + +XCEXIT endp + +;-------------------------------------------------------------------------- + + PAGE + +CENTER MACRO NAMELIST + PUSH BP ; SAVE CURRENT BP + MOV BP,SP ; POINT AT STACK WITH BP +WORKOFS = 0 + IRP ANAME, ; FOR EACH WORKING VARIABLE + IFNB <&ANAME> +WORKOFS = WORKOFS-2 ; WE WILL ALLOCATE ONE + DOEQU &ANAME,%WORKOFS ; WORD ON THE STACK THAT + ENDIF + ENDM ; IS UNDER SS,BP + ADD SP,WORKOFS + ENDM + +DOEQU MACRO NAME,VALUE +&NAME EQU &VALUE + ENDM + +CEXIT MACRO VALUE + MOV SP,BP + POP BP + RET + ENDM + + PAGE + +; INPUT PARAMATERS PASSED ON STACK + +PARMS STRUC + +OLD_BP DW ? ; SAVED BP +RETADD DW ? ; RETURN ADDRESS +PARM_1 DW ? +PARM_2 DW ? +PARM_3 DW ? +PARM_4 DW ? +PARM_5 DW ? +PARM_6 DW ? +PARM_7 DW ? +PARM_8 DW ? + +PARMS ENDS + +SAVE_SS DW 0 +SAVE_SP DW 0 + + PAGE + +;************************************************************************ +; ; +; Subroutine Name: ; +; getpspbyte ; +; ; +; Subroutine Function: ; +; get a byte from PSP ; ; +; ; +; Input: ; +; SS:[BP]+PARM1 = offset in PSP ; +; ; +; Output: ; +; AL = byte from PSP:offset ; +; ; +; C calling convention: ; +; char = getpspbyte(offset); ; +; ; +;************************************************************************ + +MOFFSET EQU PARM_1 ;AN000; + + ASSUME CS:PGROUP ;AN000; + ASSUME DS:DGROUP ;AN000; + ASSUME ES:DGROUP ;AN000; + ASSUME SS:DGROUP ;AN000; + + PUBLIC _GETPSPBYTE ;AN000; +_GETPSPBYTE PROC NEAR ;AN000; + + CENTER ;AN000; + + PUSH DS ;AN000; + + MOV DS,_PSP ;AN000; get save PSP segment + MOV SI,[BP].MOFFSET ;AN000; get offset into PSP + LODSB ;AN000; get PSP byte + MOV AH,0 ;AN000; zero high byte + + POP DS ;AN000; + + CEXIT ;AN000; + +_GETPSPBYTE ENDP + + +;************************************************************************ +; ; +; Subroutine Name: ; +; putpspbyte ; +; ; +; Subroutine Function: ; +; put a byte into PSP ; ; +; ; +; Input: ; +; SS:[BP]+MVALUE = byte in AL ; +; SS:[BP]+MOFFSET = offset in PSP ; +; ; +; Output: ; +; none ; +; ; +; C calling convention: ; +; putpspbyte(offset,char); ; +; ; +;************************************************************************ + + +MVALUE EQU PARM_2 ;AN000; +MOFFSET EQU PARM_1 ;AN000; + + ASSUME CS:PGROUP ;AN000; + ASSUME DS:DGROUP ;AN000; + ASSUME ES:DGROUP ;AN000; + ASSUME SS:DGROUP ;AN000; + + PUBLIC _PUTPSPBYTE ;AN000; +_PUTPSPBYTE PROC NEAR ;AN000; + + CENTER ;AN000; + + PUSH ES ;AN000; + + MOV AX,[BP].MVALUE ;AN000; get byte to store in PSP + MOV ES,_PSP ;AN000; get saved PSP segment + MOV DI,[BP].MOFFSET ;AN000; get offset in PSP + STOSB ;AN000; store the byte + + POP ES ;AN000; + + CEXIT ;AN000; + +_PUTPSPBYTE ENDP + + +;------------------------------------------------------------------- +; +; MODULE: crit_err_handler() +; +; PURPOSE: Supplies assembler exit routines for +; critical error situations +; +; CALLING FORMAT: +; crit_err_handler; +;------------------------------------------------------------------- + public _crit_err_handler ;AN000; + public vector ;AN000; +vector dd 0 ;AN000; +; ;AN000; +_crit_err_handler proc near ;AN000; + pushf ;AN000; + push ax ; save registers ;AN000; + push ds ;AN000; + mov ax,dgroup ;get C data segment ;AN000; + mov ds,ax ;AN000; + mov ax,word ptr ds:_old_int24_off ;get int24 offset ;AN000; + mov word ptr cs:vector,ax ;AN000; + mov ax,word ptr ds:_old_int24_off+2 ;get int24 segment ;AN000; + mov word ptr cs:vector+2,ax ;AN000; + pop ds ;restore registers ;AN000; + pop ax ;AN000; +; ;AN000; + call dword ptr cs:vector ; invoke DOS err hndlr ;AN000; + cmp al,ABORT ; what was the user's response ;AN000; + jnge retry ; ;AN000; +; ;AN000; + mov ax,dgroup ;get C data segment ;AN000; + mov ds,ax ;AN000; + mov es,ax ;AN000; + call _Reset_appendx ; restore user's orig append/x ;AN000; +; ;AN000; + mov ax,(RET_EXIT shl 8)+XABORT ; return to DOS w/criterr error ;AN000; + int 21h ; ;AN000; +retry: ;AN000; + iret ;AN000; +; ;AN000; +_crit_err_handler endp ;AN000; +_text ends ;AN000; + end XCMAIN ;AN000; + \ No newline at end of file -- cgit v1.2.3