This file declares macroinstructions for interaction with Disk Operation System - DOS.
DOS services run in 16bit real CPU mode.
dosapi HEAD ; Start of interface block includable to other programs. INCLUDEHEAD1 "cpuext.htm", "status16.htm"
%Par4 %SET BP+24 %Par3 %SET BP+22 %Par2 %SET BP+20 %Par1 %SET BP+18 %ReturnAX %SET BP+14 %ReturnCX %SET BP+12 %ReturnDX %SET BP+10 %ReturnBX %SET BP+08 %ReturnSP %SET BP+06 %ReturnBP %SET BP+04 %ReturnSI %SET BP+02 %ReturnDI %SET BP+00
DosAPI %MACRO INT=21h, \ AL=,AH=,CL=,CH=,DL=,DH=,BL=,BH=,AX=,CX=,DX=,BX=,BP=,SP=,SI=,DI=,DS=,ES=, \ al=,ah=,cl=,ch=,dl=,dh=,bl=,bh=,ax=,cx=,dx=,bx=,bp=,sp=,si=,di=,ds=,es= %intNr %SET 0x21 ; Interrupt 0x21 will be used if not specified otherwise. %kwlength %SETA %=# ; %kwlength is now the number of keyword operands in DosAPI invokation. k %FOR 1..%kwlength ; Loop through all keyword operands in DosAPI invokation. %kw %SET %=*{%k} ; %kw is now something like AH=5 or INT=21h. %kwsize %SETS %kw ; Number of characters in keyword operand %kw. %key %SET ; Split the operand by = to %key and %value. Start with empty %key. %i %SETA 1 ; Start with the 1st character. %REPEAT %IF "%kw[%i]" === "=" %EXITREPEAT ; Equal-sign found, the split is done. %ELSE %key %SET %key%kw[%i] ; Append the %i-th character and continue. %i %SETA %i + 1 %ENDIF %UNTIL %i > %kwsize %value %SET %kw[%i+1..%&] %IF "%key" == "INT" %intNr %SET %value ; Save the interrupt number for later to the variable %intNr. %ELSE %IF "%key"==="" || "%value"==="" %ERROR 'Bad parameter "%key=%value", ignored.' %ELSE MOV %key,%value ; Emit the instruction which loads the register %key. %ENDIF %ENDIF %ENDFOR k ; Process the next keyword operand. INT %intNr ; Finally emit the DOS service call. %ENDMACRO DosAPI
RETN
if segment register CS is the same as it was at the program entry.Errorlevel=
, this value may also be specified as an ordinal operand.
TerminateProgram %MACRO Errorlevel=0 %IF %# = 1 ; If ordinal provided. MOV AL,%1 %ELSE MOV AL,%Errorlevel %ENDIF MOV AH,0x4C INT 0x21 %ENDMACRO TerminateProgram
Errorlevel=
, this value may also be specified as an ordinal operand.
TerminateStayResident %MACRO ResidentParagraphs, Errorlevel=0 %IF "%1" !== "DX" MOV DX,%1 %ENDIF %IF %# = 2 ; If two ordinal provided. MOV AL,%2 %ELSE MOV AL,%Errorlevel %ENDIF MOV AH,0x31 INT 0x21 %ENDMACRO TerminateStayResident
Macro StdOutput writes one or more concatenated strings to the standard output or to other equipment identified by the DOS device Handle number.
Strings are either zero-terminated, or the keyword
Size=
must specify its size in bytes. The terminating NUL character is never written.
If keyword Eol=Yes
, macro writes CR+LF after all strings.
StdOutput %MACRO String1,String2,,,Size=-1, Handle=1, Eol=No OpNr %FOR 1..%#, STEP=1 PUSHW %Handle, %Size, %1 CALL StdOutput@RT: %SHIFT 1 %ENDFOR OpNr %IF "%Eol[1]"!=="N" PUSHW %Handle, 2, =W(0x0A0D) CALL StdOutput@RT: %ENDIF StdOutput@RT: PROC1 PUSHAW MOV BP,SP PUSH ES,DS POP ES MOV DI,[%Par1] ; Pointer to String. MOV CX,[%Par2] ; String maximal size. MOV BX,[%Par3] ; Output Handle. JCXZ .90: MOV DX,DI SUB AX,AX CLD REPNE SCASB JNE .50: DEC DI .50: SUB DI,DX XCHG CX,DI MOV AH,0x40 ; DosAPI Write to file via handle. INT 0x21 ; Write CX bytes from DS:DX to handle BX. JC .90: CMP AX,CX .90:POP ES POPAW RET 3*2 ENDPROC1 StdOutput@RT: %ENDMACRO StdOutput
Macro StdInput reads a line terminated with CR (ASCII 13) from standard input or from other equipment identified by the DOS device Handle number.
StdInput %MACRO Buffer, Size=, Handle=0 MOV BX,%Handle %IF "%Size" === "" MOV CX,SIZE# %Buffer %ELSE MOV CX,%Size %ENDIF MOV DX,%Buffer MOV AH,0x3F INT 0x21 %ENDMACRO StdInput
Macro GetArg retrieves ArgNumber-th parameter provided on command line.
Parameters on the command line may be separated with unquoted
white spaces or unquoted commas. Single aphostrophe cannot be used as quote.
The returned argument is not zero terminated. Quotes surrounding the argument are returned, too.
Runtime procedure GetArg@RT is also used in macro GetArgCount , its function is controlled by the ArgNumber parameter.
GetArg %MACRO ArgNumber %IF "%ArgNumber" !== "AL" MOV AL,%ArgNumber %ENDIF CALL GetArg@RT GetArg@RT PROC1 INCLUDEHEAD1 status16.htm, cpuext.htm ; Flags (they will be kept in BX) which describe the parsing process: %InArg %SETA 0x01 ; Parsing within argument. %InQuotes %SETA 0x02 ; Parsing within quoted argument. %ExpSep %SETA 0x04 ; Separator (comma or space) is required after the closing quote. %Pending %SETA 0x08 ; The previous argument wasn't counted yet. ; Registers employment: ; AL is parsed character. ; AH is argument counter. ; BL is parsing status with flags defined above. ; BH is 0 in GetArgCount, or ArgNr>0 in GetArg. ; DX points to the end of arguments (to the Carriage-return). ; SI is the parsing pointer. Always between 0x81 and DX. ; DI points to the 2nd character of currently parsed argument. ; CX points 1 char after the currently parsed argument terminating separator (comma or space). ; BP is stack frame pointer. ; ES is paragraph address of PSP. PUSHAW MOV BP,SP MOV BX,AX SUB AX,AX SHL BX,8 ; BH is now 0 in GetArgCount, or ArgNr MOV SI,0x80 ; Offset of PSP.CmdArgSize byte. CLD SEGES LODSB MOV DX,SI ADD DX,AX ; ES:DX now points to the CR which terminates command-line parameters. .10:TEST BH JZ .15: CMP AH,BH JAE .End: ; End if ArgNumber-th argument was just parsed to DI..CX. .15:CMP SI,DX JA .70: ; Check if end-of-arguments reached. SEGES LODSB Dispatch AL,0x0D, 0x22, 0x2C ; Jump if AL=carriage-return, quote, comma. CMP AL,0x20 JBE .0x20: ; Jump if AL is a white-space. ; Otherwise AL is an ordinary character without syntactic significance. JNSt BX,%Pending,.40: .20:DEC SI ; Previous argument is terminating. .30:RstSt BX,%Pending+%InArg+%InQuotes MOV CX,SI INC AH JMP .10: .40:JSt BX,%InArg,.10: JSt BX,%ExpSep,.Error: .50:SetSt BX,%InArg MOV DI,SI JMP .10: .0x22: ; Quote. JSt BX,%Pending,.20: JNSt BX,%InQuotes, .60: RstSt BX,%InQuotes+%InArg ; Closing quote. SetSt BX,%ExpSep+%Pending JMP .10: .60:JSt BX,%InArg|%ExpSep,.Error:; Opening quote. SetSt BX,%InQuotes JNSt BX,%Pending, .50: JMP .50: .0x2C: ; Comma. .0x20: ; White space. JSt BX,%InQuotes, .10: RstSt BX,%ExpSep JSt BX,%Pending,.30: JNSt BX,%InArg, .10: RstSt BX,%InArg SetSt BX,%Pending JMP .10: .Error: SHR AX,8 STC JMP .90: .70:INC SI .0x0D: ; Carriage-Return. JSt BX,%InQuotes, .Error: JSt BX,%InArg, .80: JNSt BX,%Pending, .End: .80:MOV CX,SI INC AH .End: TEST BH JZ .85: CMP AH,BH ; Set CF=1 when the required BH-th argument is not provided. JC .Error: DEC CX CMPB [SI-2],' ' ; Trim the trailing separators, if any. JE .83: CMPB [SI-2],',' JE .83: INC CX .83:SUB CX,DI DEC DI MOV [%ReturnCX],CX MOV [%ReturnSI],DI .85:SHR AX,8 ; Return the highest argument number in AX. CLC .90:MOV [%ReturnAX],AX POPAW RET ENDPROC1 GetArg@RT %ENDMACRO GetArg
GetArgCount %MACRO GetArg 0 %ENDMACRO GetArgCount
ENDHEAD dosapi ; End of interface block.