home *** CD-ROM | disk | FTP | other *** search
- LONG EQU 0
-
- IF LONG
- TITLE _natol.asm Numeric ASCII to long full
- ;
- NAME _natol
- ELSE
- TITLE _natoi.asm Numeric ASCII to integer full
- ;
- NAME _natoi
- ENDIF ; IF LONG
-
- INCLUDE DOS.MAC
- IF LDATA
- IF LONG
- SUBTTL Long Integer, Large Data Model
- ELSE
- SUBTTL Standard Integer, Large Data Model
- ENDIF ; IF LONG
- ELSE ; Small data
- IF LONG
- SUBTTL Long Integer, Small Data Model
- ELSE
- SUBTTL Standard Integer, Small Data Model
- ENDIF ; IF LONG
- ENDIF ; IF LDATA
- IF LONG
-
- ; SYNOPSIS
- ;
- ; result = _natol(p, number);
- ;
- ; int result Reason for termination
- ; 0 for end of non-empty input
- ; string
- ; 1 for non-numeric character
- ; 2 for empty input string
- ; 3 for no digits before a
- ; non-numeric character
- ; 4 for overflow
- ; char **p Pointer to pointer to current character
- ; At start, start of string
- ; At end, offset of terminating
- ; character
- ; unsigned long *number Pointer to converted number.
- ; _natol does not change number if
- ; the input string is empty, so the
- ; calling program can have a default
- ; value, or if there is overflow. In
- ; the latter case, the calling program
- ; should set it to a defined value. I
- ; plan to use LONG_MAX, LONG_MIN and
- ; ULONG_MAX from limits.h.
- ;
- ; DESCRIPTION
- ; This functions calculates the unsigned long value of the string
- ; pointed at by p. Under normal conditions, it returns this value in
- ; number. I intend it to be an internal function to atol_ful and atoul_ful,
- ; which will be extensions of the standard function atol which include both
- ; a pointer to the terminating character of the input string and a result
- ; indicator.
- ;
- ; To compile natoi, set LONG EQU 0.
-
- ELSE ; Not LONG
-
- ; SYNOPSIS
- ;
- ; result = _natoi(p, number);
- ;
- ; int result Reason for termination
- ; 0 for end of non-empty input
- ; string
- ; 1 for non-numeric character
- ; 2 for empty input string
- ; 3 for no digits before a
- ; non-numeric character
- ; 4 for overflow
- ; char **p Pointer to pointer to current character
- ; At start, start of string
- ; At end, offset of terminating
- ; character
- ; unsigned int *number Pointer to converted number.
- ; _natoi does not change number if
- ; the input string is empty, so the
- ; calling program can have a default
- ; value, or if there is overflow. In
- ; the latter case, the calling program
- ; should set it to a defined value. I
- ; plan to use INT_MAX, INT_MIN and
- ; UINT_MAX from limits.h.
- ;
- ; DESCRIPTION
- ; This functions calculates the unsigned int value of the string
- ; pointed at by p. Under normal conditions, it returns this value in
- ; number. I intend it to be an internal function to atoi_ful and atoui_ful,
- ; which will be extensions of the standard function atol which include both
- ; a pointer to the terminating character of the input string and a result
- ; indicator.
-
- ;
- ; To compile natol, set LONG EQU 1.
- ENDIF ; IF LONG
-
- ; I will compile this function for Lattice C, Version 3.10.
-
- ; WRITTEN BY: Lew Paper
- ; DATE WRITTEN: August 27, 1986
-
- ;
- ; This comment is a fragment from Lattice file TEMPLATE.ASM.
- ; "The following statements show how you would define the arguments for
- ; this function, which we'll assume is called with an integer, a double,
- ; and a pointer. The SETX statement defines the symbol X with a value
- ; equal to the size of the BP save area and the return address area. This
- ; makes it possible to access arguments via this kind of coding:
- ;
- ; MOV AX,[BP+X].ARG1 ; get first argument"
- ;
- SETX
- IF LDATA
- ARGS STRUC
- p DD ? ; Pointer to current character of string.
- number DD ? ; Pointer to converted number.
- ARGS ENDS
- ELSE
- ARGS STRUC
- p DW ? ; Pointer to current character of string.
- number DW ? ; Pointer to converted number.
- ARGS ENDS
- ENDIF ; IF LDATA
- ;
-
- ; Termination conditions
- END_STRING EQU 0
- NON_NUMERIC EQU 1
- EMPTY_STRING EQU 2
- EMPTY_NON_NUMERIC EQU 3
- OVERFLOW EQU 4
-
- IF LONG
- ; digit is the registers AX and DX, with AX the low order.
- ; accum is the registers BX and CX, with BX the low order.
- ELSE
- ; digit is the register AX.
- ; accum is the register BX.
- ENDIF ; IF LONG
-
- CLEAR_ACCUM MACRO ;; Initially clear accum
- IF LONG
- XOR BX,BX ;; 0 => low order accum
- XOR CX,CX ;; 0 => high order accum
- ELSE
- XOR BX,BX ;; 0 => accum
- ENDIF ;; IF LONG
- ENDM ;; CLEAR_ACCUM
-
- GET_DIGIT MACRO ;; Clear digit and get the next one
- IF LONG
- XOR AH,AH ;; 0 => high byte of low order accum
- XOR DX,DX ;; 0 => high order accum
- LODSB ;; Next character => low byte of low
- ;; order accum
- ;; Increment SI
- ELSE
- XOR AH,AH ;; 0 => high byte of accum
- LODSB ;; Next character => low byte of accum
- ;; Increment SI
- ENDIF ;; IF LONG
- ENDM ;; GET_DIGIT
-
- SHIFT_LEFT_1 MACRO ;; Shift accum left one place.
- IF LONG
- SHL CX,1 ;; High order accum
- SHL BX,1 ;; Low order accum
- ADC CX,0 ;; Add carry to high order accum
- ELSE
- SHL BX,1
- ENDIF ;; IF LONG
- ENDM ;; SHIFT_LEFT_1
-
- ADD_ACCUM MACRO ;; Add digit to accum. Set carry for
- ;; overflow.
- SHIFT_LEFT_1 ;; 2 * accum. No overflow possible.
- IF LONG
- ADD AX,BX ;; Add 2 * low order accum to digit
- ADC DX,CX ;; Add 2 * accum to digit. No
- ;; overflow possible
- ELSE
- ADD AX,BX ;; Add 2 * accum to digit. No overflow
- ;; possible
- ENDIF ;; IF LONG
- SHIFT_LEFT_1 ;; 4 * accum. No overflow possible.
- IF LONG
- SHL CX,1 ;; High order accum
- JC add_accum_exit ;; Overflow
- SHL BX,1 ;; Low order accum
- ADC CX,0 ;; 8 * accum
- ELSE
- SHL BX,1 ;; 8 * accum
- JC add_accum_exit ;; Overflow
- ENDIF ; IF LONG
- IF LONG
- ADD BX,AX ;; Low order of new accum
- ADC CX,DX ;; New accum
- ELSE
- ADD BX,AX ;; New accum
- ENDIF ;; IF LONG
- add_accum_exit:
- ENDM ;; ADD_ACCUM
-
- SAVE_POINTER MACRO ;; Save pointer to last character in
- ;; calling program
- DEC SI ; Point back to terminating character
- IF LDATA
- MOV WORD PTR ES:[DI],SI ; Save offset of terminating character
- ELSE
- MOV WORD PTR [DI],SI ; Save offset of terminating character
- ENDIF ; IF LDATA
- ENDM ;; Save pointer
-
- SAVE_NUMBER MACRO ;; Save accum in number
- IF LDATA
- LDS SI,[BP+X].number ; Pointer to number
- ELSE
- MOV SI,[BP+X].number ; Pointer to number
- ENDIF ; IF LDATA
- IF LONG
- MOV WORD PTR [SI],BX ; Low order word of number
- MOV WORD PTR [SI+2],CX ; High order word of number
- ELSE
- MOV [SI],BX ; Number
- ENDIF ; IF LONG
- ENDM ;; SAVE_NUMBER
-
- PSEG ; initiate program segment
-
- ;
- IF LONG
- BEGIN _natol ; establish procedure name, etc.
- ELSE
- BEGIN _natoi ; establish procedure name, etc.
- ENDIF ; IF LONG
- PUSH BP ; save caller's stack frame pointer
- MOV BP,SP ; establish our stack frame pointer
-
-
- IF LDATA
- PUSH DS ; Save DS for large data model
- PUSH ES ; and ES
- ENDIF ; LDATA
- PUSH SI ; Lattice recommends for future
- PUSH DI
-
- IF LDATA
- LES DI,[BP+X].p ; Pointer to pointer to first
- ; character of string
- LDS SI,ES:[DI] ; Pointer to first character of string
- ELSE
- MOV DI,[BP+X].p ; Pointer to pointer to first
- ; character of string
- MOV SI,[DI] ; Pointer to first character of string
- ENDIF ; IF LDATA
-
- CLEAR_ACCUM ; 0 => accumlator register(s)
-
- GET_DIGIT ; First digit
- OR AX,AX ; Is the string empty?
- JZ empty_string_exit ; Yes
- SUB AL,'0' ; Convert character to digit
- JL empty_non_numeric_exit
- CMP AL,9 ; Is it a digit?
- JG empty_non_numeric_exit
- ; No
- MOV BL,AL ; No need to multiply for the first
- ; digit.
- next_digit:
- GET_DIGIT ; Subsequent digit
- OR AX,AX ; Is the string done?
- JZ end_string_exit ; Yes
- SUB AL,'0' ; Convert character to digit
- JL non_numeric_exit
- CMP AL,9 ; Is it a digit?
- JG non_numeric_exit ; No
- ; Multiply accum register(s) by 10 and add digit. Set carry for overlow.
- ADD_ACCUM
- JNC next_digit
- MOV AX,OVERFLOW
- ; In all other cases, this function terminates with a non-numeric
- ; character, so SI points one character beyond it. The next instruction
- ; points SI one character beyond the numeric character which caused the
- ; overflow. SAVE_POINTER will reduce it to the offending character.
- INC SI
- JMP SHORT reset_p
-
- empty_string_exit:
- MOV AX,EMPTY_STRING
- JMP SHORT reset_p
-
- empty_non_numeric_exit:
- MOV AX,EMPTY_NON_NUMERIC
-
- reset_p:
- SAVE_POINTER ; Save offset of terminating character
- JMP SHORT restore_segs
-
- end_string_exit:
- SAVE_POINTER ; Save offset of terminating character
- SAVE_NUMBER ; Save accum in number
- MOV AX,END_STRING
- JMP SHORT restore_segs
-
- non_numeric_exit:
- SAVE_POINTER ; Save offset of terminating character
- SAVE_NUMBER ; Save accum in number
- MOV AX,NON_NUMERIC
-
- restore_segs:
- POP DI ; Restore saved registers
- POP SI
- IF LDATA
- POP ES
- POP DS
- ENDIF ; IF LDATA
- POP BP
- RET SIZE ARGS
- IF LONG
- _natol ENDP ; end the procedure "_natol"
- ELSE
- _natoi ENDP ; end the procedure "_natoi"
- ENDIF ; IF LONG
- ENDPS ; end the program segment
- END ; end the source file
-
-