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 can be included to 16bit DOS programs written in EuroAssembler.
It 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 or segment 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
↑ 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, but separating white spaces and commas are stripped off.

Runtime procedure GetArg@RT is also used in macro GetArgCount , its functionality is controlled by the ArgNumber parameter.

Dump of PSP:80h when the DOS program launched with parameters /1 "2":
07 20 2F 31 20 22 32 22 0D / 1 " 2 " CR
Dump of PSP:80h when the DOS program launched without parameters:
00 0D CR
Input
ArgNumber is ordinal number (1..254) of the required command-line parameter. It can also be provided in 16bit register or memory variable.
ArgNumber=-1 is a special case when this macro is used by GetArgCount and it returns number of arguments in AX instead of argument string in ES:SI,CX.
ES= is paragraph address of PSP , as it was set when DOS program starts.
Output
CF=0,
SI is offset of the first byte of argument in PSP segment ES,
CX is the size of argument in bytes. CX=0 when the argument is empty (white spaces only).
Error
CF=1 bad syntax - odd number of quotes.
CX=0,
SI= unchanged.
Example
CmdLine: /C "file1", "file2" --help GetArg 4: │ │ │ └SI CX=6 GetArg 3: │ │ └SI CX=7 GetArg 2: │ └SI CX=7 GetArg 1: └SI CX=2 AX=1
See also
GetArgCount
GetArg %MACRO ArgNumber
        PUSHW %ArgNumber
        CALL GetArgDos16@RT
GetArgDos16@RT:: PROC1
   PUSHAW
    MOV BP,SP
    SUB AX,AX      ; AL will be the parsed character.
    SUB CX,CX      ; CX is argument counter.
    MOV [%ReturnCX],CX
    MOV SI,0x80    ; Offset of PSP.CmdArgSize byte.
    CLD
    LODSB [ES:SI]  ; ES is paragraph address of PSP.
    MOV DX,SI
    MOV BX,SI
    ADD DX,AX      ; ES:DX now points to the CR which terminates command-line parameters.
.10:MOV DI,SI
    CMP CX,[%Par1] ; %Par1 is the number of requested argument.
    JAE .50:
.20:CMP SI,DX
    JNB .50:       ; If no more arguments are available.
    LODSB [ES:SI]
    CMP AL,' '
    JBE .20:
    DEC SI
    INC CX
    MOV BX,SI      ; BX points to the brutton begining of CX-th argument.
    MOV DI,SI      ; DI points to the brutto end of current argument.
.30:CMP SI,DX
    JNB .10:
    LODSB [ES:SI]
    CMP AL,'"'
    JNE .40:
.35:CMP SI,DX
    CMC
    JC .90:        ; CF signalizes syntax error - unpaired quotes.
    LODSB [ES:SI]
    CMP AL,'"'
    JNE .35:       ; Inside the quoted string.
    JMP .30:
.40:CMP AL,','
    JE .10:
    CMP AL,' '
    JA .30:
.45:CMP SI,DX
    JNB .10:
    LODSB [ES:SI]
    CMP AL,' '
    JNA .45:
    CMP AL,','
    JE .10:
    DEC SI
    JMP .10:
.50:CMPW [%Par1],-1 ; Test if invoked from GetArgCount with ArgNr= -1.
    JNE .60:
    MOV [%ReturnCX],CX
    JMP .80:
.60:CMP CX,[%Par1]
    STC
    JNE .90:
    MOV SI,BX      ; Brutto CX-th argument found at SI..DI. Trim spaces and commas.
.65:CMP SI,DI
    JNB .75:
    LODSB [ES:SI]
    CMP AL,' '
    JBE .65:
    CMP AL,','
    JE .65:
    DEC SI
.70:DEC DI
    MOV AL,[ES:DI]
    CMP AL,' '
    JBE .70:
    CMP AL,','
    JE .70:
    INC DI         ; Netto argument is now at SI..DI.
.75 MOV [%ReturnSI],SI
    SUB DI,SI
    JC .80:        ; Return CX=0 when the netto size is not positive.
    MOV [%ReturnCX],DI
.80:CLC
.90:POPAW
   RET 2
  ENDPROC1 GetArgDos16@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 white-space 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,
CX=number of arguments on the command line which launched the program.
Error
CF=1 bad syntax of arguments,
CX=0.
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 -1
   %ENDMACRO GetArgCount
↑ 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 their size in bytes. The terminating NUL character is never written.

If keyword Eol=Yes, macro writes CR+LF after all strings.

Input
DS= segment of all strings.
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 strings have been written.
Output
CF=0
Error
CF=1
Depends on
DosAPI
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 StdOutputDos16@RT:
       %SHIFT 1
     %ENDFOR OpNr
     %IF %Eol
       PUSHW %Handle, 2, -1
       CALL StdOutputDos16@RT:
     %ENDIF
StdOutputDos16@RT:: PROC1 ; StdCalled with %Par1=StringPtr,%Par2=Size,%Par3=Handle.
   PUSHAW
    MOV BP,SP
    PUSH ES,DS
     POP ES
     MOV DI,[%Par1] ; Pointer to String.
     MOV CX,[%Par2] ; String maximal size.
     MOV BX,[%Par3] ; Standard handle.
     JCXZ .90:
     CMP DI,-1      ; This sginalizes Eol request.
     JE .Eol:
     MOV DX,DI
     SUB AX,AX
     CLD
     REPNE SCASB
     JNE .50:
     DEC DI
.50: SUB DI,DX
     DosAPI AH=0x40,BX=BX,CX=DI,DX=DX ; WRITE TO FILE OR DEVICE.
.80: JC .90:
     CMP AX,CX      ; Set CF in not all characters have been written.
.90:POP ES
    POPAW
   RET 3*2
.Eol:PUSH DS
      PUSH SS
      POP DS
      PUSHW 0x0A0D  ; Temporary store CR+LF on stack.
      DosAPI AH=0x40,BX=BX,CX=CX,DX=SP ; WRITE TO FILE OR DEVICE.
      INC SP,SP     ; Discard CR+LF, preserve CF.
     POP DS
     JMPS .80:
   ENDPROC1 StdOutputDos16@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.
DS= segment of the Buffer.
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,
CX=number of bytes actually read and stored to Buffer.
Error
CF=1,
CX=DOS error code.
Depends on
DosAPI
Remark
Input from keyboard is terminated with the Enter key. CR+LF are stored to Buffer, too.
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
    %IF "%Size" === ""
       PUSHW %Handle, SIZE# %Buffer, %Buffer
    %ELSE
       PUSHW %Handle, %Size, %Buffer
    %ENDIF
    CALL StdInputDos16@RT
StdInputDos16@RT:: PROC1 ; StdCalled with %Par1=Buffer,%Par2=Size,%Par3=Handle.
    PUSHAW
      MOV BP,SP
      DosAPI AH=0x3F,BX=[%Par3],DX=[%Par1],CX=[%Par2] ; READ FROM FILE OR DEVICE.
      MOV [%ReturnCX],AX
    POPAW
    RET 3*2
   ENDP1 StdInputDos16@RT::
  %ENDMACRO StdInput
↑ 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 registers CS, SS, SP have the same value as they had 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.
Depends on
DosAPI
See also
TerminateStayResident
Remark
This macro is equivalent to DosAPI AH=0x4C,AL=Errorlevel.
Examples
TerminateProgram Errorlevel=[WorstErrLevel] ; Keyword value (from memory). TerminateProgram [WorstErrLevel] ; Ordinal value (from memory). TerminateProgram 8 ; Immediate value.
TerminateProgram %MACRO Errorlevel=0
     %IF %# = 1   ; If ordinal provided.
        %IF "%1" !== "AL"
          MOV AL,%1
        %ENDIF
     %ELSE        ; Errorlevel is specified as keyword.
        %IF "%Errorlevel" !== "AL"
          MOV AL,%Errorlevel
        %ENDIF
     %ENDIF
     DosAPI AH=0x4C,AL=AL ; TERMINATE WITH RETURN CODE.
    %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 other than DL,DH, 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.
Depends on
DosAPI
See also
TerminateProgram
Remark
This macro is equivalent to DosAPI AH=0x31,AL=Errorlevel,DX=ResidentParagraphs.
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
     DosAPI AH=0x31,AL=AL,DX=DX ; TERMINATE AND STAY RESIDENT.
   %ENDMACRO TerminateStayResident
 ENDHEAD dosapi ; End of interface block.

▲Back to the top▲