home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 009 / atov_ex.arc / _NATOIL.ASM next >
Encoding:
Assembly Source File  |  1986-09-01  |  8.8 KB  |  336 lines

  1. LONG    EQU    0
  2.  
  3.     IF    LONG
  4.     TITLE    _natol.asm  Numeric ASCII to long full
  5. ;
  6.     NAME    _natol
  7.     ELSE
  8.     TITLE    _natoi.asm  Numeric ASCII to integer full
  9. ;
  10.     NAME    _natoi
  11.     ENDIF        ; IF LONG
  12.  
  13.     INCLUDE DOS.MAC
  14.     IF    LDATA
  15.     IF    LONG
  16.     SUBTTL    Long Integer, Large Data Model
  17.     ELSE
  18.     SUBTTL    Standard Integer, Large Data Model
  19.     ENDIF        ; IF LONG
  20.     ELSE        ; Small data
  21.     IF    LONG
  22.     SUBTTL    Long Integer, Small Data Model
  23.     ELSE
  24.     SUBTTL    Standard Integer, Small Data Model
  25.     ENDIF        ; IF LONG
  26.     ENDIF        ; IF LDATA
  27.     IF    LONG
  28.  
  29. ;    SYNOPSIS
  30. ;
  31. ;    result = _natol(p, number);
  32. ;
  33. ;    int result    Reason for termination
  34. ;                0 for end of non-empty input
  35. ;                  string
  36. ;                1 for non-numeric character
  37. ;                2 for empty input string
  38. ;                3 for no digits before a
  39. ;                  non-numeric character
  40. ;                4 for overflow
  41. ;    char **p    Pointer to pointer to current character
  42. ;                At start, start of string
  43. ;                At end, offset of terminating 
  44. ;                    character
  45. ;    unsigned long *number    Pointer to converted number.
  46. ;            _natol does not change number if
  47. ;            the input string is empty, so the
  48. ;            calling program can have a default
  49. ;            value, or if there is overflow.  In
  50. ;            the latter case, the calling program
  51. ;            should set it to a defined value.  I
  52. ;            plan to use LONG_MAX, LONG_MIN and
  53. ;            ULONG_MAX from limits.h.
  54. ;
  55. ;    DESCRIPTION
  56. ;    This functions calculates the unsigned long value of the string
  57. ; pointed at by p.  Under normal conditions, it returns this value in
  58. ; number.  I intend it to be an internal function to atol_ful and atoul_ful,
  59. ; which will be extensions of the standard function atol which include both
  60. ; a pointer to the terminating character of the input string and a result
  61. ; indicator.
  62. ;
  63. ;    To compile natoi, set LONG EQU 0.
  64.  
  65.     ELSE        ; Not LONG
  66.  
  67. ;    SYNOPSIS
  68. ;
  69. ;    result = _natoi(p, number);
  70. ;
  71. ;    int result    Reason for termination
  72. ;                0 for end of non-empty input
  73. ;                  string
  74. ;                1 for non-numeric character
  75. ;                2 for empty input string
  76. ;                3 for no digits before a
  77. ;                  non-numeric character
  78. ;                4 for overflow
  79. ;    char **p    Pointer to pointer to current character
  80. ;                At start, start of string
  81. ;                At end, offset of terminating 
  82. ;                    character
  83. ;    unsigned int *number    Pointer to converted number.
  84. ;            _natoi does not change number if
  85. ;            the input string is empty, so the
  86. ;            calling program can have a default
  87. ;            value, or if there is overflow.  In
  88. ;            the latter case, the calling program
  89. ;            should set it to a defined value.  I
  90. ;            plan to use INT_MAX, INT_MIN and
  91. ;            UINT_MAX from limits.h.
  92. ;
  93. ;    DESCRIPTION
  94. ;    This functions calculates the unsigned int value of the string
  95. ; pointed at by p.  Under normal conditions, it returns this value in
  96. ; number.  I intend it to be an internal function to atoi_ful and atoui_ful,
  97. ; which will be extensions of the standard function atol which include both
  98. ; a pointer to the terminating character of the input string and a result
  99. ; indicator.
  100.  
  101. ;
  102. ;    To compile natol, set LONG EQU 1.
  103.     ENDIF        ; IF LONG
  104.  
  105. ;    I will compile this function for Lattice C, Version 3.10.
  106.  
  107. ;    WRITTEN BY:   Lew Paper
  108. ;    DATE WRITTEN: August 27, 1986
  109.  
  110. ;
  111. ; This comment is a fragment from Lattice file TEMPLATE.ASM.
  112. ; "The following statements show how you would define the arguments for
  113. ; this function, which we'll assume is called with an integer, a double,
  114. ; and a pointer.  The SETX statement defines the symbol X with a value
  115. ; equal to the size of the BP save area and the return address area.  This
  116. ; makes it possible to access arguments via this kind of coding:
  117. ;
  118. ;    MOV    AX,[BP+X].ARG1        ; get first argument"
  119. ;
  120.     SETX
  121.     IF    LDATA
  122. ARGS    STRUC
  123. p    DD    ?    ; Pointer to current character of string.
  124. number    DD     ?    ; Pointer to converted number.
  125. ARGS    ENDS
  126.     ELSE
  127. ARGS    STRUC
  128. p    DW    ?    ; Pointer to current character of string.
  129. number    DW    ?    ; Pointer to converted number.
  130. ARGS    ENDS
  131.     ENDIF        ; IF LDATA
  132. ;
  133.  
  134. ; Termination conditions
  135. END_STRING      EQU 0
  136. NON_NUMERIC      EQU 1
  137. EMPTY_STRING     EQU 2
  138. EMPTY_NON_NUMERIC EQU 3
  139. OVERFLOW         EQU 4
  140.  
  141.     IF    LONG
  142. ; digit is the registers AX and DX, with AX the low order.
  143. ; accum is the registers BX and CX, with BX the low order.
  144.     ELSE
  145. ; digit is the register AX.
  146. ; accum is the register BX.
  147.     ENDIF        ; IF LONG
  148.  
  149. CLEAR_ACCUM MACRO    ;; Initially clear accum
  150.     IF    LONG
  151.     XOR    BX,BX    ;; 0 => low order accum
  152.     XOR    CX,CX    ;; 0 => high order accum
  153.     ELSE
  154.     XOR    BX,BX    ;; 0 => accum
  155.     ENDIF        ;; IF LONG
  156.     ENDM        ;; CLEAR_ACCUM
  157.  
  158. GET_DIGIT    MACRO        ;; Clear digit and get the next one
  159.     IF    LONG
  160.     XOR    AH,AH    ;; 0 => high byte of low order accum
  161.     XOR    DX,DX    ;; 0 => high order accum
  162.     LODSB        ;; Next character => low byte of low
  163.             ;;                   order accum
  164.             ;; Increment SI
  165.     ELSE
  166.     XOR    AH,AH    ;; 0 => high byte of accum
  167.     LODSB        ;; Next character => low byte of accum
  168.             ;; Increment SI
  169.     ENDIF        ;; IF LONG
  170.     ENDM        ;; GET_DIGIT
  171.  
  172. SHIFT_LEFT_1 MACRO    ;; Shift accum left one place.
  173.     IF    LONG
  174.     SHL    CX,1    ;; High order accum
  175.     SHL    BX,1    ;; Low order accum
  176.     ADC    CX,0    ;; Add carry to high order accum
  177.     ELSE
  178.     SHL    BX,1
  179.     ENDIF        ;; IF LONG
  180.     ENDM        ;; SHIFT_LEFT_1
  181.  
  182. ADD_ACCUM    MACRO        ;; Add digit to accum.  Set carry for
  183.             ;; overflow.
  184.     SHIFT_LEFT_1    ;; 2 * accum.  No overflow possible.
  185.     IF    LONG
  186.     ADD    AX,BX    ;; Add 2 * low order accum to digit
  187.     ADC    DX,CX    ;; Add 2 * accum to digit.  No
  188.             ;; overflow possible 
  189.     ELSE
  190.     ADD    AX,BX    ;; Add 2 * accum to digit.  No overflow
  191.             ;; possible
  192.     ENDIF        ;; IF LONG
  193.     SHIFT_LEFT_1    ;; 4 * accum.  No overflow possible.
  194.     IF    LONG
  195.     SHL    CX,1    ;; High order accum
  196.     JC    add_accum_exit    ;; Overflow
  197.     SHL    BX,1    ;; Low order accum
  198.     ADC    CX,0    ;; 8 * accum
  199.     ELSE
  200.     SHL    BX,1    ;; 8 * accum
  201.     JC    add_accum_exit    ;; Overflow
  202.     ENDIF        ; IF LONG
  203.     IF    LONG
  204.     ADD    BX,AX    ;; Low order of new accum
  205.     ADC    CX,DX    ;; New accum
  206.     ELSE
  207.     ADD    BX,AX    ;; New accum
  208.     ENDIF        ;; IF LONG
  209. add_accum_exit:
  210.     ENDM        ;; ADD_ACCUM
  211.  
  212. SAVE_POINTER MACRO    ;; Save pointer to last character in
  213.             ;; calling program
  214.     DEC    SI    ; Point back to terminating character
  215.     IF    LDATA
  216.     MOV    WORD PTR ES:[DI],SI    ; Save offset of terminating character
  217.     ELSE
  218.     MOV    WORD PTR [DI],SI    ; Save offset of terminating character
  219.     ENDIF        ; IF LDATA
  220.     ENDM        ;; Save pointer
  221.  
  222. SAVE_NUMBER MACRO    ;; Save accum in number
  223.     IF    LDATA
  224.     LDS    SI,[BP+X].number    ; Pointer to number
  225.     ELSE
  226.     MOV     SI,[BP+X].number    ; Pointer to number
  227.     ENDIF        ; IF LDATA
  228.     IF LONG
  229.     MOV    WORD PTR [SI],BX    ; Low order word of number
  230.     MOV    WORD PTR [SI+2],CX    ; High order word of number
  231.     ELSE
  232.     MOV    [SI],BX    ; Number
  233.     ENDIF        ; IF LONG
  234.     ENDM        ;; SAVE_NUMBER
  235.  
  236.     PSEG        ; initiate program segment
  237.  
  238. ;
  239.     IF    LONG
  240.     BEGIN    _natol    ; establish procedure name, etc.
  241.     ELSE
  242.     BEGIN    _natoi    ; establish procedure name, etc.
  243.     ENDIF        ; IF LONG
  244.     PUSH    BP            ; save caller's stack frame pointer
  245.     MOV     BP,SP            ; establish our stack frame pointer
  246.  
  247.  
  248.     IF    LDATA
  249.     PUSH    DS    ; Save DS for large data model
  250.     PUSH    ES    ; and ES
  251.     ENDIF        ; LDATA
  252.     PUSH    SI    ; Lattice recommends for future
  253.     PUSH    DI
  254.  
  255.     IF    LDATA
  256.     LES    DI,[BP+X].p    ; Pointer to pointer to first 
  257.             ; character of string
  258.     LDS    SI,ES:[DI]    ; Pointer to first character of string
  259.     ELSE
  260.     MOV    DI,[BP+X].p    ; Pointer to pointer to first
  261.             ; character of string
  262.     MOV    SI,[DI]    ; Pointer to first character of string
  263.     ENDIF        ; IF LDATA
  264.  
  265.     CLEAR_ACCUM    ; 0 => accumlator register(s)
  266.  
  267.     GET_DIGIT    ; First digit
  268.     OR    AX,AX    ; Is the string empty?
  269.     JZ    empty_string_exit    ; Yes
  270.     SUB    AL,'0'    ; Convert character to digit
  271.     JL    empty_non_numeric_exit
  272.     CMP    AL,9    ; Is it a digit?
  273.     JG    empty_non_numeric_exit
  274.             ; No
  275.     MOV    BL,AL    ; No need to multiply for the first
  276.             ; digit.
  277. next_digit:
  278.     GET_DIGIT    ; Subsequent digit
  279.     OR    AX,AX    ; Is the string done?
  280.     JZ    end_string_exit    ; Yes
  281.     SUB    AL,'0'    ; Convert character to digit
  282.     JL    non_numeric_exit
  283.     CMP    AL,9    ; Is it a digit?
  284.     JG    non_numeric_exit    ; No
  285. ; Multiply accum register(s) by 10 and add digit.  Set carry for overlow.
  286.     ADD_ACCUM
  287.     JNC    next_digit
  288.     MOV    AX,OVERFLOW
  289. ; In all other cases, this function terminates with a non-numeric
  290. ; character, so SI points one character beyond it.  The next instruction
  291. ; points SI one character beyond the numeric character which caused the
  292. ; overflow.  SAVE_POINTER will reduce it to the offending character.
  293.     INC    SI
  294.     JMP    SHORT reset_p
  295.  
  296. empty_string_exit:
  297.     MOV    AX,EMPTY_STRING
  298.     JMP    SHORT reset_p
  299.  
  300. empty_non_numeric_exit:
  301.     MOV    AX,EMPTY_NON_NUMERIC
  302.  
  303. reset_p:
  304.     SAVE_POINTER    ; Save offset of terminating character
  305.     JMP    SHORT restore_segs
  306.  
  307. end_string_exit:
  308.     SAVE_POINTER    ; Save offset of terminating character
  309.     SAVE_NUMBER    ; Save accum in number
  310.     MOV    AX,END_STRING
  311.     JMP    SHORT restore_segs
  312.  
  313. non_numeric_exit:
  314.     SAVE_POINTER    ; Save offset of terminating character
  315.     SAVE_NUMBER    ; Save accum in number
  316.     MOV    AX,NON_NUMERIC
  317.  
  318. restore_segs:
  319.     POP    DI    ; Restore saved registers
  320.     POP    SI
  321.     IF    LDATA
  322.     POP    ES    
  323.     POP    DS
  324.     ENDIF        ; IF LDATA
  325.     POP    BP
  326.     RET    SIZE ARGS
  327.     IF    LONG
  328. _natol    ENDP        ; end the procedure "_natol"
  329.     ELSE
  330. _natoi    ENDP        ; end the procedure "_natoi"
  331.     ENDIF        ; IF LONG    
  332.     ENDPS                ; end the program segment
  333.     END                ; end the source file
  334.  
  335.  
  336.