EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

dosapi.htm
Enumerations
%StdCall16
Macros
DosAPI
GetArg
GetArgCount
StdInput
StdOutput
TerminateProgram
TerminateStayResident

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"
↑ %StdCall16
This assignments define preprocessing %variables useful to refer stack frame in 16bit StdCall calling convention.
Example
PUSH Factor3,Factor2,Factor1 CALL Multiply JMP Continue: Multiply PROC PUSHAW MOV BP,SP MOV AX,[%Par1] MUL [%Par2],DATA=WORD JC .Overflow: MUL [%Par3],DATA=WORD .Overflow:MOV [%ReturnAX],AX MOV [%ReturnDX],DX POPAW RET 3*2 ENDPROC Multiply
 %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 INT=21h, reg1=value1, reg2=value2,,,
Macro DosAPI provides interaction with Disk Operation System (DOS), with the help of software-called interruptions.
Documented
[IntList]
Input
INT= is the interrupt number, if other than 0x21.
regX=valueX. Arbitrary number of keyword parameters can be specified and the corresponding 8bit or 16bit general-purpose register will be loaded with its value before the interrupt is called.
Registers are loaded in the order as specified in the macro invocation.
Names of registers and the INT= key are case-sensitive but both uppercase and lowercase may be used.
Output
Values returned from interrupt service are defined in the documentation.
Error
As specified in the documentation.
Examples
LDS DX,[NewTimerHandlerFarProc] DosAPI AH=0x25,AL=8 ; Set new vector DS:DX for interrupt 8. ; DosAPI AX=0x2508 ; This equivalent invocation is 1 byte shorter.
See also
BiosAPI
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 invocation.
k   %FOR 1..%kwlength ; Loop through all keyword operands in DosAPI invocation.
%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 Id=5910,'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
↑ TerminateProgram Errorlevel=0
This macro exits from the running DOS program and returns to DOS.
It also specifies the Errorlevel (plain number 0..255) which can be used to inform the batch script which launched the program whether the it terminated normally or with some error condition.
Programs in COM format can alternatively terminate with a simple instruction RETN if segment register CS is the same as it was at the program entry.
Documented
[IntList]
Input
Errorlevel=0 is immediate byte or 8bit register or memory operand.
Beside the keyword Errorlevel=, this value may also be specified as an ordinal operand.
When this argument is omitted, it defaults to 0.
Output
is not applicable.
See also
TerminateStayResident
Examples
TerminateProgram Errorlevel=[WorstErrLevel] ; Keyword value (from memory). TerminateProgram 8 ; Immediate value.
TerminateProgram %MACRO Errorlevel=0
     %IF %# = 1   ; If ordinal provided.
        MOV AL,%1
     %ELSE
        MOV AL,%Errorlevel
     %ENDIF
     MOV AH,0x4C
     INT 0x21
    %ENDMACRO TerminateProgram
↑ TerminateStayResident   ResidentParagraphs, Errorlevel=0
This macro exits the running DOS program and returns to DOS, but leaves part of its memory allocated (resident).
It also specifies the Errorlevel (plain number 0..255) which can be used to inform the batch script which launched the program whether it terminated normally or due to some error.
Documented
[IntList]
Input
ResidentParagraphs is the size of resident memory in 16byte paragraphs (OWORDs).
It may be immediate value or 16bit memory variable or register (preferably DX).
Errorlevel=0 is immediate byte or 8bit register or memory operand.
Beside the keyword Errorlevel=, this value may also be specified as an ordinal operand.
When this argument is omitted, it defaults to 0.
Output
is not applicable.
See also
TerminateProgram
Examples
TerminateStayResident DX,0 ;
TerminateStayResident %MACRO ResidentParagraphs, Errorlevel=0
     %IF "%1" !== "DX"
       MOV DX,%1
     %ENDIF
     %IF %# = 2   ; If two ordinals provided.
       MOV AL,%2
     %ELSE
       MOV AL,%Errorlevel
     %ENDIF
     MOV AH,0x31
     INT 0x21
    %ENDMACRO TerminateStayResident
↑ StdOutput String1, String2,,, Size=-1, Handle=1, Eol=No

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.

Input
StringX is offset of (ASCIIZ) string of 8byte characters. Its segment is DS.
Size=-1 is the maximal possible string size. If its left to -1 (default), strings must be zero-terminated. This parameter applies to all ordinal operads.
Handle=1 is the number of device handle for the output. Standard output handles are Eol=No. If Yes, two additional characters CR and LF will be written on output after all string have been written.
Output
CF=0
Error
CF=1
Remark
If Eol=Yes, DS must be the segment with literals.
Examples
StdOutput Message, Eol=Yes StdOutput Eol=Yes ; Write new line (CR+LF) only. StdOutput =B"Page header",=B(12),Handle=4 ; Print header and then eject page from the printer at LPT1.
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
↑ StdInput Buffer, Size=, Handle=0

Macro StdInput reads a line terminated with CR (ASCII 13) from standard input or from other equipment identified by the DOS device Handle number.

Input
Buffer is offset of memory where the input line will be stored. Its segment is assumed in DS.
Size= is the Buffer size. If omitted (default), macro will use SIZE# attribute of the Buffer.
Handle=0 is the number of device handle for the input. Standard input handles are
Output
CF=0, AX=number of bytes actually read and stored to Buffer.
Error
CF=1, AX= DOS error code.
Remark
Input from keyboard is terminated with the Enter key. CR+LF are stored to Buffer as well.
See also
DosAPI AX=0x3301 how to abort the input by Ctrl-Break.
BiosAPI INT=0x16 for keyboard functions.
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
↑ GetArg   ArgNumber

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.

Input
ArgNumber is ordinal number of the required parameter, starting with 1. It can also be provided in 8bit register or memory variable.
ES= is paragraph address of PSP , as it was set when DOS program starts.
Output
CF=0,
AX=ArgNumber,
SI is offset of the first byte of argument in PSP segment ES,
CX is the size of argument in bytes.
Error
CF=1 bad syntax - odd number of quotes or if requested argument was not provided,
AX=ArgNumber,
SI=CX= unchanged.
Example
CmdLine: /C "file1", "file2" --help GetArg 4: │ │ │ └SI CX=6 AX=4 GetArg 3: │ │ └SI CX=7 AX=3 GetArg 2: │ └SI CX=7 AX=2 GetArg 1: └SI CX=2 AX=1
See also
GetArgCount
Depends on
%StdCall16, Dispatch
status16.htm
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
This macro counts arguments provided on the command line of the executed program.
Arguments may be separated with unquoted spaces or unquoted commas. Multiple separators are treated like a single space. Single apostrophe cannot be used as a quote.
Input
ES= is paragraph address of PSP , as it was set when DOS program starts.
Output
CF=0,
AX=number of arguments on the command line which launched the program.
Error
CF=1 bad syntax of arguments,
AX= number of valid arguments.
Depends on
GetArg
Example
All examples of the command lines below will return ArgCount=4.
Program.exe arg1 arg2 arg3 arg4 Program.exe "arg1",arg2 "arg3" arg4 Program.exe arg1,arg2,,,, "arg3,arg3" "arg4
GetArgCount %MACRO
     GetArg 0
    %ENDMACRO GetArgCount
 ENDHEAD dosapi ; End of interface block.

▲Back to the top▲