Calling Macros in DOS.INC and BIOS.INC You are responsible for saving and restoring registers used in macros. The "Registers used" field identifies registers to save. Macros that accept address parameters use internal macros that allow you to specify addresses in several ways. The macro automatically identifies the type of the argument and handles it appropriately. For example, assume the following declarations: String DB "test$" pString DW Str fpString DD Str Given these values, the macro @DispStr (which displays the string at DS:DX) has the following effects: Kind of argument Example Value loaded Label of byte variable @DispStr String DS:OFFSET String Near pointer variable @DispStr pString DS:pString Far pointer variable @DispStr fpString fpString[2]:fpString[0] Constant @DispStr 0 DS:0 Pointer in register @DispStr si DS:SI Near Pointer with segment @DispStr pString,es ES:pString Constant with segment @DispStr 0,es ES:0 Register with segment @DispStr di,es ES:DI Note that if a far pointer or a segment is given, DS must be saved before the macro call and restored afterward. Segments may be given as registers, constants, or word variables. In syntax, parameters enclosed in brackets are optional. Paramaters sometimes have a leading symbol to indicate that the argument must have a certain type, as shown below: Leading Symbol Example Limitation # #return Must be constant & &vector Must be offset address as described above $ $terminator May be constant or register, but not memory Parameters with no leading symbol may be constants, registers, or variables. Parameters are 16-bit except where noted in the description. Symbols must be previously defined before they can be passed as arguments to most of the DOS macros. Generally this means that data must be declared before code in the source file. DOS Macro Syntax and Description KEYBOARD INPUT @GetKey (01h, 07h, 08h, 0Ch) Gets a keystroke from the keyboard Syntax: @GetKey [#echo] [,[#break] [,#clearbuf]] Arguments: echo = nonzero to echo keystroke - default yes break = nonzero to accept Control-C - default yes clearbuf = nonzero to clear keyboard buffer - default no (Arguments may be omitted to get defaults) Return: ASCII code of key in AL Registers used: AX used for all, DL used if echo on and ctrl-c off @GetStr (0Ah) Gets a string from the keyboard Syntax: @GetStr &buffer [,[$terminator] [,[#limit] [,segment]]] Arguments: buffer = Offset of buffer where string will be stored Byte 1 = Maximum length of string (before call) Byte 2 = Actual length of string (after call) Byte 3+ = Bytes of string terminator = Terminating byte - usually null (0) or $ (24h) limit = Maximum length of string (if not given as argument, must be in buffer before macro call) segment = Segment of buffer (DS if not given) Return: Pointer to string in SI, length of string in BX Registers used: AX, DX, BX, SI OUTPUT @DispCh (02h) Displays one or more characters to screen Syntax: @DispCh char [,char]... Arguments: char = 8-bit ASCII code Return: Code in AL Registers used: AX and DL @PrtCh (05h) Prints one or more characters to LPT1 Syntax: @PrtCh char [,char]... Arguments: char = 8-bit ASCII code Return: Code in AL Registers used: AX and DL @DispStr (09h) Displays a $-terminated string Syntax: @DispStr &address [,segment] Arguments: address = Address of string terminated by "$" (24h) segment = Segment of address string (DS if not given) Return: None Registers used: AX and DS DEVICE I/O @Read (3Fh) Reads data from a file or device Syntax: @Read &buffer, length [,[handle] [,segment]] Arguments: buffer = Offset of buffer where data will be stored length = Length of data in bytes handle = File or device handle; if none given, keyboard (handle 0) is assumed segment = Segment of address string (DS if not given) Return: If carry clear, bytes read in AX Registers used: Always AX, DX, BX, and CX; DS if segment changed @Write (40h) Writes data to a file or device Syntax: @Write &buffer, length, [,[handle] [,segment]] Arguments: buffer = Offset of buffer where data is stored length = Length of data in bytes handle = File or device handle; if none given, screen (handle 1) is assumed segment = Segment of address string (DS if not given) Return: If carry clear, bytes written in AX Registers used: Always AX, DX, BX, and CX; DS if segment changed FILE CONTROL @MakeFil (3Ch, 5Ah, 5Bh) Creates a file Syntax: @MakeFil &path [,[attrib] [,[segment] [,#kind]]] Arguments: path = ASCIIZ string of file attrib = File atrribute (0 is default if none given) segment = Segment of address string (DS if not given) kind = If none given, a file is always created even if one already exists. Under DOS 3+ "tmp" can be given to create a unique file or "new" to create file only if one doesn't already exist. Return: If carrry clear, file handle in AX Registers used: Always AX, DX, and CX; DS if segment changed @OpenFil (3Dh) Opens a file for input or output Syntax: @OpenFil &path, #access [,segment] Arguments: path = ASCIIZ string of file access = File access code segment = Segment of address string (DS if not given) Return: If carrry set, error code in AX Registers used: Always AX and DX; DS if segment changed @ClosFil (3Eh) Closes an open file handle Syntax: @ClosFil handle Arguments: handle = Previously opened file handle Return: If carrry set, error code in AX Registers used: AX and BX @DelFil (41h) Deletes a specified file Syntax: @DelFil &path [,segment] Arguments: path = Offset of ASCIIZ filespec segment = Segment of path (DS if none given) Return: If carrry set, error code in AX Registers used: AX and DX; DS if segment changed @MoveFil (56h) Moves or renames a file by changing its path specification. Syntax: @MoveFil &old, &new [,[segold] [,segnew]] Arguments: old = Offset of file spec to be renamed new = Offset of new file spec segold = Segment of old name (DS if none given) segnew = Segment of new name (ES if none given) Return: If carry set, error code in AX Registers used: AX, DX, and DI; DS and ES if corresponding segments changed @GetFirst (4Eh) and @GetNext (4Fh) Parses file specifications (optionally including wild cards) into file names Syntax: @GetFirst &path [,[attribute] [,segment]] @GetNext Arguments: path = Offset of ASCIIZ filespec (can have wild cards) attribute = File attribute to search for (0 for normal if none given) segment = Segment of path (DS if none given) Return: If carrry set, error code in AX Registers used: @GetFirst = AX, CX, and DX; DS if segment changed @GetNext = AX only @GetDTA (1Ah) and @SetDTA (2Fh) Gets or sets the Disk Transfer Address (DTA) Syntax: @GetDTA @SetDTA &buffer [,segment] Arguments: buffer = Offset of new DTA buffer segment = Segment of new DTA buffer (DS if none given) Return: @GetDTA = ES:BX points to DTA @SetDTA = None Registers used: AX for both; DS and DX for @SetDTA; ES and BX for @GetDTA @GetFilSz (42h) Gets the file size by moving the file pointer to end of the file. Note that the file pointer is reset to zero. Thus this macro should not be called during operations that move the pointer. Syntax: @GetFilSz handle Arguments: handle = Previously opened file handle Return: If carrry clear, file length in DX:AX Registers used: AX, BX, CX, and DX @MovePrtAbs and @MovePtrRel (42h) Moves the file pointer in an open file. The pointer can be moved to an absolute position, or relative to its current position. Syntax: @MovePrtAbs handle [,distance] @MovePrtRel handle [,distance] Arguments: handle = Previously opened file handle distance = Distance to move pointer - must be a 16-bit constant or a 16- or 32-bit variable; or leave blank and set distance in CX:DX before macro call Return: If carrry clear, file pointer position in DX:AX Registers used: AX, BX, CX, and DX DIRECTORY CONTROL @MkDir, (39h), @RmDir (3Ah), and @ChDir (3Bh) Creates, deletes, or changes to the specified directory Syntax: @MkDir &path [,segment] @RmDir &path [,segment] @ChDir &path [,segment] Arguments: path = Offset of ASCIIZ string to segment = Segment of path (DS if none given) Return: If carrry set, error code in AX Registers used: AX and DX; DS if segment changed @GetDir (47h) Returns the current directory of the specified drive Syntax: @GetDir &path [,[drive] [,segment]] Arguments: buffer = Offset of buffer to receive ASCIIZ directory drive = 8-bit drive number - 0=current, 1=A, 2=B, etc. (0 if none given) segment = Segment of path (DS if none given) Return: If carrry set, error code in AX Registers used: AX, SI, and DL; DS if segment changes DRIVE CONTROL @GetDrv (0Eh) and @SetDrv (19h) Gets or sets the current drive Syntax: @GetDrv @SetDrv drive Argument: drive = 8-bit drive number (0=A, 1=B, etc.) Return: @GetDrv = Drive number in AL (0=A, 1=B, etc.) @SetDrv = Number of drives in AL Registers used: AX for both; DL for @SetDrv @ChkDrv (36h) Gets various data about a disk Syntax: @ChkDrv [drive] Argument: drive = 8-bit drive number (0=current,A=1, B=2, etc.); if none given, current assumed Return: AX = Sectors per cluster (-1 if drive invalid) BX = Available clusters CX = Bytes per sector DX = Clusters per drive Registers used: AX, BX, CX, and DX PROCESS CONTROL @Exit (4Ch) Exits to DOS with return code Syntax: @Exit [#return] Argument: return = 8-bit code to return to DOS; if none given, AL is used Return: None Registers used: AX @Exec (4Bh) Executes a child process or an overlay Syntax: @Exec path, params [,[segpath] [,[segparams] [,overlay]]] Arguments: path = Offset of ASCIIZ filespec to be executed params = Offset of process parameter block segpath = Segment of filespec (DS if none given) segparams = Segment of parameter block (ES if none given) overlay = If not defined, normal process executed; if defined, overlay executed Return: If carry set, error code Registers used: AX, SI, and DI; DS and ES if corresponding segments given @GetRet (4Dh) Gets the return code of a child process Syntax: @GetRet Argument: None Return: Return code in AX Register used: AX @TSR (31h) Terminates a program, but leaves it resident in memory Syntax: @TSR paragraphs [,#return] Arguments: return = Code to return to DOS; if none, AL used paragraphs = Memory in paragraphs (16 bytes) to allocate for resident program Return: None Registers used: AX and DX MEMORY CONTROL @FreeBlok (49h) Frees a block of memory Syntax: @FreeBlok [segment] Argument: segment = Starting address of memory to be freed; if none, ES address assumed Return: If carry set, error code in AX Register used: AX; ES if segment given @GetBlok (48h) Allocates a block of memory Syntax: @GetBlok paragraphs Argument: paragraphs = Paragraphs (16 bytes) of memory wanted Return: AX and ES = Segment address of allocated memory BX = Paragraphs actually allocated (may be less than requested if memory is short) Register used: AX and BX @ModBlok (48h) Modifies an allocated block of memory Syntax: @ModBlok paragraphs [,segment] Argument: paragraphs = Paragraphs (16 bytes) of memory wanted segment = Starting address of memory to be freed; if none, ES address assumed Return: If carry set, error code in AX, else: ES = Segment address of allocated memory BX = If carry is clear, paragraphs allocated Register used: AX and BX; ES if segment given MISCELLANEOUS @GetDate (2Ah) and @SetDate (2Bh) Gets or sets the system date Syntax: @GetDate @SetDate month, day, year Arguments: year = 16-bit year (1980-2099) month = 8-bit month (1-12) day = 8-bit day (1-31) Return: For @GetDate: AL = Day of week (0 = Sunday, 1 = Monday, etc.) CX = Year (1980-2099) DL = Month (1-12) DH = Day (1-31) For @SetDate: AL = If date was valid 0, else -1 Registers used: AX, CX, and DX @GetTime (2Ch) and @SetTime (2Dh) Gets or sets the system time Syntax: @GetTime @SetTime hour,minute,second,hundredth Arguments: hour = 8-bit hour (0-23) minute = 8-bit hour (0-59) second = 8-bit hour (0-59) hundredth = 8-bit hour (0-99) Return: For @GetTime: CL = Hour (0-23) CH = Minute (0-59) DL = Second (0-59) DH = Hundredth (0-99) For @SetTime: AL = If time was valid 0, else -1 Registers used: AX, CX, and DX @GetVer (30h) Gets the DOS version Syntax: @GetVer Argument: None Return: AL = Major version (0 for versions prior to 2.0) AH = Minor version BH = OEM serial number BL:CX = 24-bit user number Register used: AX, BX, and CX @GetInt (35h) and @SetInt (25h) Gets or sets the vector for a specified interrupt routine Syntax: @GetInt #interrupt @SetInt #interrupt, &vector [,segment] Arguments: interrupt = 8-bit interrupt number vector = Offset of interrupt routine segment = Segment of routine - if none given, DS assumed for data; segment ignored for code labels Return: @GetInt = None @SetInt = ES:BX points to interrupt routine Registers used: AX for both; ES and BX for @GetInt; DS and DS for @SetInt BIOS Macro Syntax and Description MODE, PAGE, AND COLOR CONTROL @GetMode (I 10h F 0Fh) Gets the current video mode and page Syntax: @GetMode Arguments: None Return: AL = Mode AH = Width in characters BH = Page Registers used: AX and BH @SetMode (I 10h F 00h) Gets the current video mode and page Syntax: @SetMode mode Arguments: mode = 8-bit video mode Return: none Registers used: AX @SetColor (I 10h F 0Bh) Sets the background color Syntax: @SetColor color Arguments: color = 8-bit background color (0-15); border color in text modes Return: none Registers used: AX and BX @SetPalet (I 10h F 0Bh) Sets the color palette Syntax: @SetPalet color Arguments: color = 8-bit color palette (0-1 for modes 5 and 6) Return: none Registers used: AX and BX @SetPage (I 10h F 05h) Sets the video page Syntax: @SetPage page Arguments: page = 8-bit page number; 0-3 for modes 2 and 3 Return: none Registers used: AX CHARACTER AND CURSOR CONTROL @GetCur (I 10h F 04h) Gets the cursor position and size Syntax: @GetCur [page] Arguments: page = 8-bit page with cursor (if none, 0 assumed) Return: DL = Column DH = Row CL = Starting scan line CH = Ending scan line Registers used: AX, DX, CX, and BH @SetCurPos (I 10h F 02h) Sets the cursor position Syntax: @SetCurSz [column] [,[row] [,page]] Arguments: column = 8-bit column; if none, DL used row = 8-bit row; if none, DH used page = 8-bit page with cursor (if none, 0 assumed) Return: none Registers used: AX, DX, and BH @SetCurSz (I 10h F 01h) Sets the cursor size and shape by specifying active scan lines. The CGA adapter the lines are 0-7. The monochrome adapter has lines 0-13. Syntax: @SetCurSz startline, endline Arguments: startline = 8-bit starting scan line (default CGA=6; MA=12) endline = 8-bit ending scan line (default CGA=7; MA=13) Return: none Registers used: AX and CX @GetChAtr (I 10h F 08h) Gets the character and attribute at the cursor location Syntax: @GetChAtr [page] Arguments: page = 8-bit page to check (if none, 0 assumed) Return: AH = Attribute AL = ASCII character Registers used: AX and BH @PutChAtr (I 10h F 09h) and @PutCh (I 10h F 0Ah) Puts one or more characters and attributes at the current cursor position. For @PutCh, the current attribute is used in text modes and any specified attribute is ignored. Syntax: @PutChAtr [character] [,[attrib] [,[page] [,count]]] Arguments: character = 8-bit ASCII character to put; if none, AL used attrib = 8-bit attribute to put; if none, BL used page = 8-bit page to put on (if none, 0 assumed) count = Number to put (if none, 1 assumed) Return: AH = Attribute AL = ASCII character Registers used: AX, BX, CX @Scroll (I 10h F 06h and 07h) Scrolls a specified window up or down Syntax: @Scroll dist [,[attr] [,[uprow [,[upcol [,[dnrow] [,dncol]]]]] Arguments: dist = 8-bit number of lines to scroll; positive scrolls down; negative scrolls up; 0 clears attr = 8-bit attribute for blank lines (if none, 07h) uprow = Upper left row (if none, CH used) upcol = Upper left column (if none, CL used) dnrow = Lower right row (if none, DH used) dncol = Lower right column (if none, DL used) Return: none Registers used: AX, CX, DX, and BH @Cls (I 10h F 06, 08h, and 02h) Clears the screen of the current page Syntax: @Cls Arguments: None Return: None Registers used: AX, BX, CX, and DX