UCR Standard Library -- Constants


UCR StdLib v2: Constants
4.1 - Interface
4.2 - Generic Interface
4.3 - Simple Constants and Text Equates
4.4 - Macros for Common Operations.
4.4.1 - DOS
4.4.2 - ExitPgm
4.4.3 - LESI, LFSI, LFSI
4.4.4 - XFSGS, FSES, and ESFS
4.4.5 - Pshadrs


UCR StdLib v2: Constants

The UCR Standard Library (stdlib) contains a large number of constants and macros that are of interest to assembly language programmers. This section describes these values.


4.1 Interface

To access the routines in the conversions package, your assembly language module must include the file "consts.a" during assembly. You can accomplish this with either of the following include statements in your assembly code:





        include consts.a
or
        include ucrlib.a

Note that the "ucrlib.a" include file automatically includes all include files associated with the UCR Standard Library. Also note that many other include files automatically include the "consts.a" file, so it might not be necessary to include "consts.a" in your main program if you are using other modules in the standard library. Note that the "consts.a" file also includes the "macros.a" file. Many of the symbols this document discusses actually appear in the "macros.a" file.

The consts.a include file defines some private symbols. The UCR Standard Library prefaces all "private" names with a dollar sign ("$"). You should not use any symbol in this package that begins with this symbol. To avoid name conflicts, you should not define any symbols in your programs that begin with a dollar sign ("$"). Note that future versions of the stdlib (that remain compatible with this release) may change "private" names. To remain compatible with future releases, you must not refer to these "private" names within your programs unless otherwise advised that this is okay.

Source code appearing in this chapter is current as of Version Two, Release 40. There may be minor changes between this source code and the current release.


4.2 Generic Interface

Many of the standard library routines use a common generic programmer's interface. Such routines let you pass parameters to them in several different locations. Common examples include in the registers, by value in the code stream (CSi), by reference in the code stream (CS), by value on the top of stack (TOS), and by reference on the top of stack (Stk). Typically, there are separate invocation macros defined for each of these variants, e.g.,





        IsAlNum                 ;Passed in AL register.

        IsAlNumCS
        dword   chrPtr          ;Passed by reference in code stream.

        push    'a'             ;Passed by value on the stack.
        IsAlNumTOS

        push    seg chrVar      ;Passed by reference on the stack.
        push    offset chrVar
        IsAlNumStk

Note that you will rarely find actual routines that pass their parameters by value in the code stream using the "CSi" suffix. The reason this is so is because most such routines use different, more descriptive names. For example, "PutsCSi" goes by the name "Print".

In addition to the above forms there are two other suffixes generally applied to stdlib routine names: "m" and "x". The "m" suffix stands for "malloc". Routines with the "m" suffix typically generate a string result and malloc storage for the string on the heap, returning a pointer to this string in the ES:DI register pair. The routines with an "x" suffix also process strings. Most stdlib routines preserve the value of the ES:DI registers when processing strings; typically, they leave the ES:DI register pair pointing at the start of the string. The routines with an "x" suffix do not preserve ES:DI, they generally leave ES:DI pointing at the zero byte of the string they processed or generated.

To make it easier to use all these different variants, the standard library typically defines a macro for each routine that lets you specify various operands using stdlib "addressing modes." The allowable addressing modes vary by routines, but they typically take one of the following forms:





        name            ;If operand field is blank, use "plain" version.
        name    var     ;Generally passes address of var in code stream (CS).
        name    const   ;Pushes const onto TOS and uses nameTOS routine.
        name    [wvar]  ;Pushes DS followed by value of wVar variable
                        ; (assumed to be a word) and calls nameSTK
        name    [dVar]  ;Pushes dword value of dVar onto stk, calls nameStk.

Since not all of these "addressing modes" are applicable to all instructions, and some instructions allow different sets of operands (including multiple operands), there are lots of special cases. Such cases are noted after the explaination for each particular routine.


4.3 Simple Constants and Text Equates

The Standard Library provides several simple numeric and textual equates for some commonly used values. The pertinent equates are:





NULL    =       0
bell    =       07h
bs      =       08h
tab     =       09h
lf      =       0ah
cr      =       0dh
nl      textequ <cr,lf>

Most of these are relatively straight-forward, only the last equate deserves any comment. The "nl" (new line) equate expands to the two-character sequence carriage return/line feed. You can use this equate anywhere it would be legal to put the two symbols "cr" and "lf" together (separated by a comma). For example, you could legally place this symbol in the operand field of a BYTE directive. However, the "nl" symbol is not legal in many places. Be aware of this problem.

Some additional text equates you may find useful are also defined in the consts.a and macros.a files:





byp     textequ <byte ptr>
wp      textequ <word ptr>
dp      textequ <dword ptr>

These symbols save you the expense of typing byte ptr, word ptr, or dword ptr when overriding a symbol's type. Note that "bp" is a reserved word (the BP register) which is why the textequates above use BYP for the override symbol.


4.4 Macros for Common Operations.

The UCR Standard Library "consts.a" file supplies macros for certain common operations. The following sections describe the purpose of these macros and their calling sequences.


4.4.1 DOS

The DOS macro calls MS-DOS using the INT 21h instruction. Without any operands, this instruction simply emits an INT 21h instruction. If you supply a single operand, the DOS macro emits an instruction that loads the AH register with the value of this operand. The (as of 10/96) definition for this macro is




DOS             macro   opcode
                ifnb    opcode
                mov     ah, opcode
                endif
                int     21h
                endm

Sample use of this macro:




                mov     al, 0   ;No error pgm return code.
                dos     4ch     ;Terminates program execution.

4.4.2 ExitPgm

The ExitPgm macro emits the necessary instructions that immediately terminate program execution and return control to the current DOS shell. Note that ExitPgm expects a system return code in the AL register. This should be zero if the program ran correctly. The ExitPgm macro uses function 4ch of the INT 21h call to do the deed. The (10/96) definition for ExitPgm is





ExitPgm         macro
                mov     ah, 4ch
                int     21h
                endm

Sample usage:




                mov     al, 2   ;Return error code 2.
                ExitPgm

4.4.3 LESI, LFSI, LFSI

The 80x86 chips do not provide an instruction that lets you load the segmented address of a memory location into a segment:register pair. True, the LDS, LES, LFS, LGS, and LSS instructions let you load a pointer into a segment:register pair, but they do not let you directly load an address into these register pairs (i.e., the LDS, LES, etc. instructions behave like mov, not lea). Since the Standard Library uses far pointers, and loading the address of an object into a segment:register pair is a common operation, the Standard Library provides several macros that let you load the address of an object into ES:DI, FS:SI, and GS:BX.




lesi            macro   adrs
                mov     di, seg adrs
                mov     es, di
                mov     di, offset adrs
                endm

lfsi            macro   adrs
                mov     si, seg adrs
                mov     fs, si
                mov     si, offset adrs
                endm

lgsi            macro
                mov     bx, seg adrs
                mov     gs, bx
                mov     bx, offset adrs
                endm

Samples:





i               word    -10
Name            byte    "c:\filename.txt",0
                 .
                 .
                 .
                lesi    i       ;Loads ES:DI with the address
                                ; of the "i" variable.
                lfsi    Name    ;Loads FS:SI with the address
                                ; of the "Name" variable.

4.4.4 XFSGS, FSES, and ESFS

Although the Standard Library's routines were designed to require as little "glue code" as necessary between calls, there are a few instances where you will find that the output from one function winds up in the wrong register pair for use as input to another function. To help with this problem, the Standard Library provides several macros that let you exchange the data in a set of segment:register pairs and move the data from one register pair to another.

The xfsgs routine exchanges the data between the FS:SI and GS:DI register pairs. The code for this macro is





xfsgs           macro
                push    fs
                push    gs
                pop     fs
                pop     gs
                xchg    si, di
                endm

The fses macro copies the data from the ES:DI register pair to the FS:SI register pair. The code for this macro is





fses            macro
                mov     si, es
                mov     fs, si
                mov     si, di
                endm

The esfs macro copies the data from the FS:SI to the ES:DI register pair. The code for this macro is





esfs            macro
                mov     di, fs
                mov     es, di
                mov     di, si
                endm

If you need other register move or exchange instructions, it is easy enough (of course) to write your own macros to accomplish this.


4.4.5 Pshadrs

Certain Standard Library calls expect the far address of an object on the stack. The pshadrs macro pushes the far address of a symbol onto the stack (segment portion first, offset second). This macro requires a single operand that must be the name of a variable or function.





pshadrs         macro   object
                push    seg object
                push    offset object
                endm

Example of usage:





                pshadrs i
                putistk         ;Expects address on TOS.