home *** CD-ROM | disk | FTP | other *** search
-
- const long_tag: string[90]
- = #0'@(#)CURRENT_FILE LAST_UPDATE Long integer math library 1.0'#0;
- #log Long integer math library 1.0
-
- (*
- * long.inc - Long integer arithmatic package:
- *
- * This set of subroutines allow you to compute with integers in the
- * range of +2,147,483,647 to -2,147,483,648.
- *
- * Long integers are stored as four bytes (or two words) and are defined by
- * the 'long' type.
- *
- * Long integers can be initialized either from a string with optionally
- * a sign and one to ten digits via the routine 'atol'. The string must be
- * of type 'longstr'.
- *
- * The routine 'itol' allows you to initialize a long from an integer.
- *
- * Some DOS functions return long integers.
- *
- * Long integers are converted to strings for display via the 'ltoa' routine.
- * It returns a string with the type of 'longstr'.
- *
- *)
-
-
- type
- long = record
- loword: integer;
- hiword: integer;
- end;
-
- longstr = string [11];
-
-
-
- procedure itol (n1: integer;
- var n2: long);
- { Convert signed to integer n1 to signed long
- n2 }
-
- begin
- n2.loword := n1;
-
- if n1 >= 0 then
- n2.hiword := 0
- else
- n2.hiword :=- 1;
- end;
-
- procedure addl (var sum: long;
- n1,
- n2: long);
- { Add long n1 to n2 producing sum: may be treated
- as signed or unsigned }
-
- begin
- inline($8B / $86 / n1 / { MOV AX,n1[bp] }
- $03 / $86 / n2 / { ADD AX,n2[bp] }
- $C4 / $BE / sum / { LES DI,sum[BP] }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $BF / $02 / $00 / { MOV DI,2 }
- $8B / $83 / n1 / { MOV AX,n1[di+bp] }
- $13 / $83 / n2 / { ADC AX,n2[di+bp] }
- $C4 / $BE / sum / { LES DI,sum[BP] }
- $26 / $89 / $45 / $02); { MOV ES:[DI]+2,AX }
-
- end;
-
- procedure subl (var diff: long;
- n1,
- n2: long);
- { subtract long n2 from n1 producing diff:
- may be treated as signed or unsigned }
-
- begin
- inline($8B / $86 / n1 / { MOV AX,n1[bp] }
- $2B / $86 / n2 / { SUB AX,n2[bp] }
- $C4 / $BE / diff / { LES DI,diff[BP] }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $BF / $02 / $00 / { MOV DI,2 }
- $8B / $83 / n1 / { MOV AX,n1[di+bp] }
- $1B / $83 / n2 / { SBB AX,n2[di+bp] }
- $C4 / $BE / diff / { LES DI,diff[BP] }
- $26 / $89 / $45 / $02); { MOV ES:[DI]+2,AX }
-
- end;
-
- function cmpl (n1: long;
- op: longstr;
- n2: long): boolean;
- { compares long n1 with n2 returning boolean:
- may be treated as signed or unsigned. op
- is a string like '>', '<', '=>', '=<', '>=',
- '<=', or '='. '<>' is NOT supported: use
- NOT(cmpl(n1,'=',n2)) instead. }
-
- var
- bool: boolean;
-
- begin
- inline($8B / $86 / n1 / { MOV AX,n1[bp] }
- $2B / $86 / n2 / { SUB AX,n2[bp] low order word difference}
- $BF / $02 / $00 / { MOV DI,2 point to high order words}
- $8B / $9B / n1 / { MOV BX,n1[di+bp] }
- $1B / $9B / n2 / { SBB BX,n2[di+bp] high order word difference}
- $30 / $ED / { XOR CH,CH }
- $8A / $8E / op / { MOV CL,op[bp] get the string length}
- $8D / $B6 / op / { LEA SI,op[bp] }
- $46 / { INC SI point to the first operator}
- $C6 / $86 / bool / $00 / { MOV bool[bp],false assume false}
- $E3 / $36 / { jcxz exit no opeators: false}
-
- { tstops: }
- $36 / $80 / $3C / $3D / { cmp byte ptr ss:[si],'='}
- $75 / $0A / { jne opt1 not an equal sign}
- $09 / $DB / { or bx,bx }
- $75 / $22 / { jnz nxtop not zero: can't be true}
- $09 / $C0 / { or ax,ax }
- $75 / $1E / { jnz nxtop not zero: can't be true}
- $EB / $21 / { jmp true hi & lo zero: true }
-
- { opt1: }
- $36 / $80 / $3C / $3E / { cmp byte ptr ss:[si],'>'}
- $75 / $0C / { jne opt2 not a greater than sign}
- $09 / $DB / { or bx,bx }
- $78 / $12 / { js nxtop neg. difference means less than}
- $75 / $15 / { jnz true pos. difference means greater
- than}
- $09 / $C0 / { or ax,ax }
- $75 / $11 / { jnz true pos. difference means greater
- than}
- $EB / $0A / { jmp nxtop no difference means equal}
-
- { opt2: }
- $36 / $80 / $3C / $3C / { cmp byte ptr ss:[si],'<'}
- $75 / $0E / { jne exit invalid operator is false}
- $09 / $DB / { or Bx,Bx }
- $78 / $05 / { js true neg. difference means less than}
-
- { nxtop: }
- $46 / { INC SI point to next operator}
- $E2 / $D1 / { LOOP tstops test until true or no more
- operators}
- $EB / $05 / { JMP EXIT true not found: exit false}
-
- { true: }
- $C6 / $86 / bool / $01); { MOV bool[bp],true set true}
-
- { exit: }
-
- cmpl := bool;
- end;
-
- procedure divl (var quo,
- rem: integer;
- n1: long;
- n2: integer);
- { Divides signed integer n2 into signed long
- n2, yielding signed integer quotient quo
- and signed integer remainder rem }
-
- begin
- inline($8B / $86 / n1 / { MOV AX,n1[bp] }
- $BF / $02 / $00 / { MOV DI,2 }
- $8B / $93 / n1 / { MOV DX,n1[bp+di] }
- $8B / $8E / n2 / { MOV CX,n2[bp] }
- $F7 / $F9 / { IDIV CX }
- $C4 / $BE / quo / { LES DI,quo[bp] }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $C4 / $BE / rem / { LES DI,rem[bp] }
- $26 / $89 / $15); { MOV ES:[DI],DX }
-
- end;
-
- procedure multl (var prod: long;
- n1,
- n2: integer);
- { Multiplies signed integer n2 by signed integer
- n2, producing signed long prod. }
-
- begin
- inline($8B / $86 / n1 / { MOV AX,n1[bp] }
- $8B / $8E / n2 / { MOV CX,n2[bp] }
- $F7 / $E9 / { IMUL CX }
- $C4 / $BE / prod / { LES DI,prod[bp] }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $26 / $89 / $55 / $02); { MOV ES:[DI+2],DX }
-
- end;
-
- procedure slrl (var quo: long;
- shift: integer);
- { Shifts quo by number of bits in 'shift' right,
- filling vacated bits left with zeros. }
-
- begin
- inline($cd / $02 / $8B / $8E / shift /
- { MOV CX,shift[bp] }
- $09 / $C9 / { OR CX,CX }
- $74 / $18 / { JZ END }
- $C4 / $BE / quo / { LES DI,quo[bp] }
- $26 / $8B / $05 / { MOV AX,ES:[DI] }
- $26 / $8B / $55 / $02 / { MOV DX,ES:[DI+2] }
-
- {SHIFT:}
- $D1 / $EA / { SHR DX }
- $D1 / $D8 / { RCR AX }
- $E2 / $FA / { LOOP SHIFT }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $26 / $89 / $55 / $02); { MOV ES:[DI+2],DX }
-
- { END: }
-
- end;
-
- procedure sarl (var quo: long;
- shift: integer);
- { Shifts long by number fo bits in 'shift'
- right, propagating the sign bit.}
-
- begin
- inline($cd / $02 / $8B / $8E / shift /
- { MOV CX,shift[bp] }
- $09 / $C9 / { OR CX,CX }
- $74 / $18 / { JZ END }
- $C4 / $BE / quo / { LES DI,quo[bp] }
- $26 / $8B / $05 / { MOV AX,ES:[DI] }
- $26 / $8B / $55 / $02 / { MOV DX,ES:[DI+2] }
-
- {SHIFT:}
- $D1 / $FA / { SAR DX }
- $D1 / $D8 / { RCR AX }
- $E2 / $FA / { LOOP SHIFT }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $26 / $89 / $55 / $02); { MOV ES:[DI+2],DX }
-
- { END: }
-
- end;
-
- procedure slll (var quo: long;
- shift: integer);
- { Shifts long by number fo bits in 'shift'
- left, filling vacated bits on right with
- zeros. }
-
- begin
- inline($cd / $02 / $8B / $8E / shift /
- { MOV CX,shift[bp] }
- $09 / $C9 / { OR CX,CX }
- $74 / $18 / { JZ END }
- $C4 / $BE / quo / { LES DI,quo[bp] }
- $26 / $8B / $05 / { MOV AX,ES:[DI] }
- $26 / $8B / $55 / $02 / { MOV DX,ES:[DI+2] }
-
- {SHIFT:}
- $D1 / $E0 / { SHL AX }
- $D1 / $D2 / { RCL DX }
- $E2 / $FA / { LOOP SHIFT }
- $26 / $89 / $05 / { MOV ES:[DI],AX }
- $26 / $89 / $55 / $02); { MOV ES:[DI+2],DX }
-
- { END: }
-
- end;
-
- function ltoa (long: long): longstr;
- { Converts a long to signed printable ASCII
- string }
-
- var
- temps: array [1..5] of char;
- strg: longstr;
-
- begin
- inline($1E / { PUSH DS }
- $FC / { CLD Set direction Forward }
- $8C / $D0 / { MOV AX,SS }
- $8E / $C0 / { MOV ES,AX }
- $8E / $D8 / { MOV DS,AX }
- $32 / $C0 / { XOR AL,AL Clear AX }
- $8D / $BE / temps / { LEA DI,TEMPS[BP] Point to working storage }
- $B9 / $05 / $00 / { MOV CX,5 Five bytes }
-
- {CLEAR:}
- $AA / { STOS BYTE PTR [DI] Clear temp variables }
- $E2 / $FD / { LOOP CLEAR -all of them }
- $B9 / $20 / $00 / { MOV CX,32 32 bits to convert }
- $8B / $9E / long / { MOV BX,LONG[BP] Load low order word }
- $BF / $02 / $00 / { MOV DI,2 ... and ... }
- $8B / $93 / long / { MOV DX,LONG[BP+DI] hi order word }
- $F7 / $C2 / $00 / $80 / { TEST DX,$8000 Negative? }
- $74 / $0A / { JZ NOCOMP Nope }
- $F7 / $D2 / { NOT DX 1's Complement }
- $F7 / $D3 / { NOT BX Both }
- $83 / $C3 / $01 / { ADD BX,1 Add 1 }
- $83 / $D2 / $00 / { ADC DX,0 Carry over }
-
- {NOCOMP: }
- $FD / { STD Set direction backward }
-
- {BITLOOP:}
- $51 / { PUSH CX Save bit counter }
- $B9 / $05 / $00 / { MOV CX,5 Five bytes = ten digits }
- $8D / $B6 / temps / { LEA SI,TEMPS[BP] Set Indices }
- $83 / $C6 / $04 / { ADD SI,4 -end of ws }
- $8B / $FE / { MOV DI,SI }
- $D1 / $E3 / { SHL BX,1 Get a Bit }
- $D1 / $D2 / { RCL DX,1 Rotate through all bits }
-
- {BITADD:}
- $AC / { LODSB Get a byte }
- $12 / $C0 / { ADC AL,AL Double adding in carry }
- $27 / { DAA Packed adjust }
- $AA / { STOSB Save it }
- $E2 / $F9 / { LOOP BITADD for another two digits }
- $59 / { POP CX get bit counter }
- $E2 / $E5 / { LOOP BITLOOP another bit }
- $FC / { CLD Go forward }
- $8D / $BE / strg / { LEA DI,strg[bp] Point to string }
- $47 / { INC DI Point to character }
- $33 / $D2 / { XOR DX,DX Clear DX - length counter}
- $BE / $02 / $00 / { MOV SI,2 Offset to hi order }
- $F7 / $82 / long / { TEST LONG[BP+SI],8000 Negative? }
- $00 / $80 / $74 / $04 / { JZ NOSIGNED Nope }
- $42 / { INC DX Set length }
- $B0 / $2D / { MOV AL,'-' Make it minus }
- $AA / { STOSB save it }
-
- {UNSIGNED:}
- $8D / $B6 / temps / { LEA SI,TEMPS[BP] Point to working storage }
- $B9 / $0A / $00 / { MOV CX,10 Ten bytes }
- $33 / $DB / { XOR BX,BX Clear BX - length counter}
-
- {UNPK:}
- $F7 / $C1 / $01 / $00 / { TEST CX,1 High order? }
- $75 / $0D / { JNZ LOWNIB nope }
- $AC / { LODSB Get packed characters }
- $8A / $E0 / { MOV AH,AL }
- $D0 / $E8 / { SHR AL,1 Hi nibble to Low nibble }
- $D0 / $E8 / { SHR AL,1 }
- $D0 / $E8 / { SHR AL,1 }
- $D0 / $E8 / { SHR AL,1 }
- $EB / $04 / { JMP OUTSTR Go process a byte }
-
- {LOWNIB:}
- $8A / $C4 / { MOV AL,AH Do the low nibble }
- $24 / $0F / { AND AL,0FH }
-
- {OUTSTR:}
- $A8 / $0F / { TEST AL,0FH Is this a zero }
- $75 / $04 / { JNZ OUTDIGIT Nope }
- $09 / $DB / { OR BX,BX Have we leading nonzeroes}
- $74 / $04 / { JZ NXTNIB nope }
-
- {OUTDIGIT:}
- $43 / { INC BX keep track of length }
- $0C / $30 / { OR AL,'0' Make it printable }
- $AA / { STOSB save it }
-
- {NXTNIB:}
- $E2 / $DB / { LOOP UNPK Do it again }
- $01 / $D3 / { ADD BX,DX Get length: is there any?}
- $75 / $04 / { JNZ SAVLEN Yep }
- $43 / { INC BX Set length }
- $B0 / $30 / { MOV AL,'0' Make it zero }
- $AA / { STOSB save it }
-
- {SAVLEN:}
- $8D / $BE / strg / { LEA DI,strg[bp] Point to string }
- $36 / $88 / $1D / { MOV SS:[DI],BL Save length }
- $1F); { POP DS }
-
- ltoa := strg; { We can't reference ltoa in inline(), so
- we do this. }
-
- end;
-
- procedure atol (strg: longstr;
- var val: long;
- var rc: integer);
- { This function mimics the Turbo val() procedure:
- strg is a one to 11 character string with
- an optional leading sign (atol accepts a
- leading '+' or '-' sign, val() only accepts
- a leading '-' sign). val is the long to
- receive the value. rc is 0 if the string
- is a null or contains a valid numeric. Else,
- rc is the point at which a nonnumeric was
- found, or the digit that caused val to overflow.
- like Turbo val() trailing or leading spaces
- are not allowed. atol accepts longs in the
- rangs +2,147,483,647 to -2,147,483,647.
- -2,147,483,648 generates an error. val()
- returns an error for -32,768. }
-
- begin
- inline($33 / $C0 { XOR AX,AX ;Clear accum }
- / $33 / $D2 { XOR DX,DX ; ...and ext }
- / $32 / $ED { XOR CH,CH ; and hi cnt }
- / $33 / $F6 { XOR SI,SI ; set rc if no chars }
- / $8A / $8E / strg { MOV CL,[strg+BP]; get length }
- / $E3 / $6D { JCXZ EXIT ; return if no length }
- / $8D / $BE / strg { LEA DI,[strg+bp]; point to string }
- / $47 { INC DI ; point to first char }
- / $BE / $FF / $FF { MOV SI,-1 ; Flag negative }
- / $36 / $80 / $3D / $2D { CMP BYTE PTR SS:[DI],'-'; Minus sign? }
- / $74 / $3F { JE NXTCHR ; Make negative }
- / $BE / $01 / $00 { MOV SI,1 ; Assume positive }
- / $36 / $80 / $3D / $2B { CMP BYTE PTR SS:[DI],'+'; Plus sign? }
- / $74 / $36 { JE NXTCHR ; go look at next char }
-
- {CHKCHR: }
- / $36 / $80 / $3D / $30 { CMP BYTE PTR SS:[DI],'0'; Numeric? }
- / $7C / $38 { JL ENDSTR ; Nope }
- / $36 / $80 / $3D / $39 { CMP BYTE PTR SS:[DI],'9'; }
- / $7F / $32 { JG ENDSTR ; Nope }
- / $BB / $0A / $00 { MOV BX,000A ; Base value }
- / $50 { PUSH AX ; Save low order }
- / $8B / $C2 { MOV AX,DX ; Get high order }
- / $F7 / $E3 { MUL BX ; Shift it }
- / $70 / $28 { JO ENDSTR ; Too big: error. }
- / $78 / $26 { JS ENDSTR }
- / $8B / $D0 { MOV DX,AX ; Temp Store Hi order }
- / $58 { POP AX ; Restore low order }
- / $52 { PUSH DX ; Save Hi order }
- / $F7 / $E3 { MUL BX ; Shift low order }
- / $5B { POP BX ; Get low order }
- / $03 / $D3 { ADD DX,BX ; Add it }
- / $78 / $1B { JS ENDSTR ; Too big, exit. }
- / $72 / $19 { JC ENDSTR }
- / $36 / $8A / $1D { MOV BL,BYTE PTR SS:[DI] ; Get the digit }
- / $32 / $FF { XOR BH,BH ; clear for add }
- / $80 / $EB / $30 { SUB BL,'0' ; Make binary }
- / $03 / $C3 { ADD AX,BX ; Add this digit }
- / $83 / $D2 / $00 { ADC DX,0 ; Whole long }
- / $78 / $0A { JS ENDSTR ; Too big, exit. }
- / $72 / $08 { JC ENDSTR }
-
- {NXTCHR: }
- / $47 { INC DI; point to next char }
- / $E2 / $C7 { LOOP CHKCHR ; again }
- / $33 / $DB { XOR BX,BX ; No error }
- / $EB / $09 / $90 { JMP RETURN }
-
- {ENDSTR: }
- / $8D / $9E / strg { LEA BX,[strg+bp]; Get addr of string }
- / $2B / $FB { SUB DI,BX ; Get offset to bad char }
- / $8B / $DF { MOV BX,DI ; Set return code }
-
- {RETURN: }
- / $0B / $F6 { OR SI,SI ; Need to adjust sign? }
- / $79 / $0A { JNS RETURN1 ; nope }
- / $F7 / $D0 { NOT AX }
- / $F7 / $D2 { NOT DX }
- / $83 / $C0 / $01 { ADD AX,1 }
- / $83 / $D2 / $00 { ADC DX,0 ; Whole long }
-
- {RETURN1: }
- / $8B / $F3 { MOV SI,BX ; Set RC }
-
- {EXIT: }
- / $C4 / $BE / rc { LES DI,DWORD PTR [BP+rc] }
- / $26 / $89 / $35 { MOV WORD PTR ES:[DI],SI ; Set RC }
- / $C4 / $BE / val { LES DI,DWORD PTR [BP+val] }
- / $26 / $89 / $05 { MOV WORD PTR ES:[DI],AX ; Low word }
- / $47 { INC DI }
- / $47 { INC DI }
- / $26 / $89 / $15); { MOV WORD PTR ES:[DI],DX ; High Word }
-
- end;
-