home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / psp_io / mathio.asm < prev    next >
Assembly Source File  |  1994-05-28  |  19KB  |  393 lines

  1. ;****************************************************************************
  2. ;                           M A T H I O . A S M
  3. ;============================================================================
  4. ; Functions to convert binary values to ASCII (displayable) format 
  5. ; as decimal, hexadecimal or binary integers.
  6. ; Functions to convert ASCII strings, representing decimal, hexadecimal
  7. ; or binary integers, to binary values.
  8. ;---------------------------------------------------------------------------
  9. ; Copyright (c) Simon Groes, 1994
  10. ;---------------------------------------------------------------------------
  11. ; Assemble with Borland Turbo Assembler v3.0
  12. ;****************************************************************************
  13.  
  14.         IDEAL
  15.         DOSSEG
  16.         MODEL   small
  17.  
  18.         LOCALS
  19.  
  20. ;-----  Insert INCLUDE "filename" directives here
  21.         INCLUDE "macro.inc"
  22.         INCLUDE "common.inc"
  23.  
  24. ;-----  Insert EQU and = equates here
  25. hexBase         =       10h
  26. binBase         =       02h
  27. decBase         =       0Ah
  28.  
  29.         DATASEG
  30.  
  31. base            dw      0
  32. wordVal         dw      0
  33. ascDigit        db      '0123456789ABCDEF'
  34. ascBuffer       db      20 DUP (0)
  35. ascBufLen       =       $ - ascBuffer
  36.  
  37. ;-----  Declare other variables with DB, DW, etc., here
  38.  
  39. ;-----  Specify any EXTRN variables here
  40.  
  41.         CODESEG
  42.  
  43. ;-----  Declare PUBLIC procedures here
  44.         PUBLIC  BinToAscii, AsciiToBin
  45.         PUBLIC  AsciiBinToBin, AsciiHexToBin, AsciiDecToBin
  46.  
  47. ;-----  Specify any EXTRN procedures here
  48.         EXTRN   strLength:proc, charToUpper:proc, strCopy:proc
  49.  
  50. ;===============================================================
  51. ; Procedure:    =*=BinToAscii=*=
  52. ;---------------------------------------------------------------
  53. ; Usage:        Public - may be used by other asm files.
  54. ; Task:         Convert 16-bit binary value to ascii format.
  55. ; Input:        ax = 16-bit value
  56. ;               bx = base (2,10,16)
  57. ;               di = offset address of buffer to hold ascii string.
  58. ;               cl = Minimum # of digits to output.
  59. ;               ch = type of leading character, if cl > # digits output
  60. ;                    (usually '0' or SPACE).
  61. ; Output:       none
  62. ; Registers:    none
  63. ; Note:         The buffer should be long enough to hold the ascii string
  64. ;               representing the maximum value of a 1-word integer
  65. ;               plus the appended 'H' plus NULL; ie 18 bytes.
  66. ;===============================================================
  67. PROC    BinToAscii
  68.  
  69.  
  70.         SaveRegs <es,di,si,dx,cx,bx,ax>       ; Save modified register(s).
  71.  
  72. ;---------------------------------------------------------------
  73. ; BinToAscii works by first dividing the original value in ax by the base.
  74. ; The remainder in dx then equals the value for the rightmost digit.
  75. ; Thereafter the quotients in ax are repeatedly divided by the base
  76. ; and the remainders in dx equal the digits from right to left.
  77. ;---------------------------------------------------------------
  78.         smove   es, ds                  ; es -> data segment
  79.         mov     si, di                  ; si = di = calling buffer.
  80.         mov     di, OFFSET ascBuffer    ; Address buffer.
  81.         add     di, ascBufLen-3         ; di -> last digit in buffer.
  82.         mov     [BYTE di+2], NULL       ; String terminator.
  83.  
  84. ;-----  Valid base ?
  85.         cmp     bx, binBase             ; Binary ?
  86.         jne     @@Dec                   ; No : Is it decimal ?
  87.         mov     [BYTE di+1], 'B'        ; Yes: Append 'B'
  88.         jmp     NEAR    @@Valid
  89. @@Dec:  cmp     bx, decBase             ; Decimal ?
  90.         jne     @@Hex                   ; No : Is it hexadecimal ?
  91.         mov     [BYTE di+1], NULL       ; Yes: Append NULL
  92.         jmp     NEAR    @@Valid
  93. @@Hex:  cmp     bx, hexBase             ; Hexadecimal ?
  94.         jne     @@Return                ; No : Invalid number, end.
  95.         mov     [BYTE di+1], 'H'        ; Yes: Append 'H'.
  96. @@Valid:
  97.         mov     [base], bx              ; Base in 'base' variable.
  98.         mov     bx, OFFSET ascDigit     ; Address 'ascDigit' table.
  99.         std                             ; Auto-decrement.
  100. @@Rpt:
  101.         or      cl, cl                  ; cl = 0 ?
  102.         jz      @@Ra                    ; Yes: Don't decrement.
  103.         dec     cl
  104. @@Ra:   cmp     ax, [base]              ; ax >= [base] ?
  105.         jb      @@Next                  ; No : Exit loop.
  106.         xor     dx, dx                  ; Clear dx.
  107.         div     [base]                  ; dxax/[base]; ax=quotient,dx=rest.
  108.         xchg    ax, dx                  ; ax=rest,dx=quotient.
  109.         xlat                            ; al = ascii digit.
  110.         stosb                           ; [es:di] = al; dec di.
  111.         xchg    ax, dx                  ; ax = quotient, dx = rest.
  112.         jmp     NEAR    @@Rpt           ; Repeat sequence.
  113.  
  114. @@Next:
  115.         xlat                            ; al = ascii digit.
  116.         mov     [BYTE es:di], al        ; [es:di] = al. di -> string.
  117.         or      cl, cl                  ; cl = 0 ?
  118.         jz      @@Copy                  ; Yes: Copy buffer to input string.
  119.         dec     di                      ; No : di -> next char.
  120.         mov     al, ch                  ; al = '0', SPACE etc.
  121.         xor     ch, ch                  ; Now cx = cl.
  122. @@Rpt2:
  123.         repnz   stosb                   ; [es:di] = al; dec di.
  124.         inc     di                      ; di -> start of string in buffer.
  125. @@Copy:        
  126.         xchg    di, si                  ; di -> call buffer; si -> string.
  127.         call    strCopy                 ; Copy to caller's buffer.
  128. @@Return:
  129.         RestoreRegs <ax,bx,cx,dx,si,di,es>
  130.         ret
  131. ENDP    BinToAscii
  132.  
  133. ;===============================================================
  134. ; Procedure:    =*=AsciiToBin=*=
  135. ;---------------------------------------------------------------
  136. ; Usage:        Public - may be used by other asm files.
  137. ; Task:         Convert string of ascii numeric characters
  138. ;               to 16-bit binary value.
  139. ; Input:        di = offset address of ascii string.
  140. ;               Note: If the string is not decimal,
  141. ;               it must be terminated with the following letters:
  142. ;               h or H - hexadecimal, b or B - binary.
  143. ; Output:       If valid number, ax = 16-bit binary value, cf = 0.
  144. ;               If invalid number, ax = 0, cf = 1.
  145. ; Registers:    ax changed.
  146. ;===============================================================
  147. PROC    AsciiToBin
  148.  
  149. ;-----  Binary, Hexadecimal or Decimal ?
  150.         call    AsciiBinToBin           ; Is it binary ?
  151.         jnc     @@Return                ; Yes: cf = 0, ax = value, end.
  152.         or      ax, ax                  ; No : Not binary or invalid number?
  153.         jnz     @@Error                 ; Invalid: End with error.
  154.         call    AsciiHexToBin           ; Is it hex ?
  155.         jnc     @@Return                ; Yes: cf = 0, ax = value, end.
  156.         or      ax, ax                  ; No : Not hex or invalid number ?
  157.         jnz     @@Error                 ; Invalid: End with error.
  158.         call    AsciiDecToBin           ; Is it decimal ?
  159.         jnc     @@Return                ; Yes: cf = 0, ax = value, end.
  160. @@Error:
  161.         xor     ax, ax                  ; ax = 0.
  162.         stc                             ; Set carry flag - error.
  163. @@Return:
  164.         ret                             ; Return to caller.
  165. ENDP    AsciiToBin
  166.  
  167. ;===============================================================
  168. ; Procedure:    =*=AsciiBinToBin=*=
  169. ;---------------------------------------------------------------
  170. ; Usage:        Public - available to other asm files.
  171. ; Task:         Convert ascii binary digit string to 16-bit value.
  172. ; Input:        di = offset address of ascii string.
  173. ; Output:       If binary, ax = 16-bit value.
  174. ;               If not binary, cf = 1.
  175. ; Registers:    ax is changed.
  176. ; Note:         A 'B' or 'b' must be appended to all binary strings.
  177. ;               If an error occurs, ax = errorcode.
  178. ;               If ax = 0, a 'B' or 'b' was not appended (not binary).
  179. ;               If ax = 0FFFFh, a 'B' or 'b' was appended, but
  180. ;                  an invalid digit (not '1' or '0') was encountered.
  181. ;===============================================================
  182. PROC    AsciiBinToBin
  183.  
  184.         SaveRegs <bx,cx,dx,si>          ; Save modified register(s).
  185.  
  186.         call    strLength               ; cx = length of string.
  187.         mov     si, di                  ; si -> ascii string.
  188.         add     si, cx                  ; si -> NULL.
  189.         dec     si                      ; si -> 'B' or 'b'.
  190.         mov     al, [BYTE si]           ; al = 'B' or 'b'.
  191.         call    charToUpper             ; al = 'B'.
  192.         cmp     al, 'B'                 ; al = 'B' ?
  193.         jne     @@NoBin                 ; No : End routine 'not binary'.
  194.  
  195. ;---------------------------------------------------------------
  196. ; Binary routine reads string of '1's and '0's, starting from the 
  197. ; least significant (left-most) character.  If a '1' is encountered, 
  198. ; the bit in dx, corresponding to the position of the '1' in the string,
  199. ; is switched on.  If a '0' is encountered, it is left off.
  200. ;---------------------------------------------------------------
  201.         dec     cx                      ; cx = # of digits.
  202.         cmp     cx, 16                  ; Too many digits ?
  203.         ja      @@Inval                 ; End, invalid number.
  204.         dec     si                      ; si -> last digit.
  205.         xor     ax, ax                  ; Clear ax.
  206.         xor     dx, dx                  ; Clear dx.
  207.         mov     bx, 0001h               ; Bit 0 = 1, all other bits = 0.
  208.         std                             ; Auto-decrement.
  209.  
  210. ;-----  Read sequence of digits and convert to single bits.
  211. @@Rpt1: lodsb                           ; al = [si], si-1.
  212.         sub     al, '0'                 ; al = 0 or 1.
  213.         test    al, 11111110b           ; If not 1 or 0,
  214.         jnz     @@Inval                 ;  end routine 'invalid digit'.
  215.         or      al, al                  ; al = 0 or 1 ?
  216.         jz      @@Bit0                  ; If 0, do nothing.
  217.         or      dx, bx                  ; If 1, insert 1 into dx.
  218. @@Bit0: shl     bx, 1                   ; Move to next bit.
  219.         loop    @@Rpt1                  ; Read next digit in string. cx-1.
  220. ;-----  Conversion loop complete - binary value in dx.
  221.         mov     ax, dx                  ; Value in ax.
  222.         clc                             ; cf = 0, no error.
  223.         jmp     NEAR    @@Return        ; End routine.
  224.  
  225. @@NoBin:
  226.         xor     ax, ax                  ; ax = error code for 'not binary'.
  227.         jmp     NEAR    @@Error
  228. @@Inval:
  229.         mov     ax, 0FFFFh              ; ax = 'invalid digit' code.
  230. @@Error:
  231.         stc                             ; Set carry flag.
  232. @@Return:
  233.         RestoreRegs <si,dx,cx,bx>       ; Restore register(s).
  234.         ret                             ; Return to caller.
  235. ENDP    AsciiBinToBin
  236.  
  237. ;===============================================================
  238. ; Procedure:    =*=AsciiHexToBin=*=
  239. ;---------------------------------------------------------------
  240. ; Usage:        Public - available to other asm files.
  241. ; Task:         Convert ascii hexadecimal digit string to 16-bit value.
  242. ; Input:        di = offset address of ascii string.
  243. ; Output:       If hexadecimal, ax = 16-bit value, cf = 0.
  244. ;               If not hexadecimal, cf = 1, ax = 0.
  245. ;               If invalid, cf = 1, ax = 0FFFFh.
  246. ; Registers:    ax is changed.
  247. ; Note:         An 'H' or 'h' must be appended to all hex strings.
  248. ;               If an error occurs, ax = errorcode.
  249. ;               If ax = 0, a 'H' or 'h' was not appended (not hex).
  250. ;               If ax = 0FFFFh, a 'H' or 'h' was appended, but
  251. ;                  an invalid digit (not '0' to 'F') was encountered.
  252. ;===============================================================
  253. PROC    AsciiHexToBin
  254.  
  255.         SaveRegs <es,bx,cx,dx,si>       ; Save modified register(s).
  256.  
  257.         smove   es, ds                  ; es -> data segment.
  258.         mov     si, di                  ; si -> ascii string.
  259.         call    strLength               ; cx = length of string.
  260.         add     si, cx                  ; si -> NULL.
  261.         dec     si                      ; si -> 'H' or 'h'.
  262.         std                             ; Auto-decrement si.
  263.         lodsb                           ; ax = [si], si -> last digit.
  264.         dec     cx                      ; cx = # digits.
  265.         call    charToUpper             ; al = 'H'.
  266.         cmp     al, 'H'                 ; al = 'H' ?
  267.         jne     @@NoHex                 ; No : End routine 'not hex'.
  268.  
  269. ;---------------------------------------------------------------
  270. ; The hexadecimal routine converts the character placed in al
  271. ; into a 4-bit binary value.  The value is then shifted to the 
  272. ; nibble (4-bit unit) corresponding to the position of the ascii 
  273. ; digit in the string.  This value is then 'or'd onto the dx register.
  274. ;---------------------------------------------------------------
  275.         cmp     cx, 4                   ; Too many digits ?
  276.         ja      @@Inval                 ; Yes: End, invalid number.
  277.         xor     ax, ax                  ; Clear ax.
  278.         xor     dx, dx                  ; Clear dl - counter.
  279.         xor     bx, bx                  ; To hold integer.
  280.         std                             ; Auto-decrement.
  281.  
  282. ; Read single digits and convert to 4-bit values.
  283. @@Rpt1: lodsb                           ; al = [si], si-1.
  284.         cmp     al, '0'                 ; digit >= '0' ?
  285.         jb      @@Inval                 ; No : Invalid digit, end.
  286.         cmp     al, '9'                 ; digit <= '9' ?
  287.         jbe     @@Sub0                  ; Yes: Goto @@Sub0.
  288.         call    charToUpper             ; Convert to uppercase.
  289.         cmp     al, 'A'                 ; digit >= 'A' ?
  290.         jb      @@Inval                 ; No : Invalid digit, end.
  291.         cmp     al, 'F'                 ; digit <= 'F' ?
  292.         ja      @@Inval                 ; No : Invalid digit, end.
  293.         sub     al, 'A'- ('9'+ 1)       ; 'A'-('9'+1)=# chars between.
  294. @@Sub0: sub     al, '0'                 ; Sub0: Subtract '0' from al.
  295. ; AL register now holds an increment into hex0toF table.
  296.         or      dl, dl                  ; dl = 0 ?
  297.         jz      @@R1a                   ; Yes: Don't shift ax.
  298.         xchg    cx, dx                  ; dx = cx; cx = dx.
  299.         shl     ax, cl                  ; Shift 4-bit value into position.
  300.         xchg    cx, dx                  ; Restore cx & dx.
  301. @@R1a:  or      bx, ax                  ; Insert 4-bit value into word.
  302.         add     dl, 4                   ; dl = dl + 4.
  303.         loop    @@Rpt1                  ; dec cx; If cx=0, exit loop.
  304. ; Conversion complete.
  305.         mov     ax, bx                  ; 16-bit value in ax.
  306.         clc                             ; Reset (clear) carry flag.
  307.         jmp     NEAR    @@Return        ; End without error.
  308. @@NoHex:
  309.         xor     ax, ax                  ; ax = error code for 'not hex'.
  310.         jmp     NEAR    @@Error
  311. @@Inval:
  312.         mov     ax, 0FFFFh              ; ax = 'invalid digit' code.
  313. @@Error:
  314.         stc                             ; Set carry flag.
  315. @@Return:
  316.         RestoreRegs <si,dx,cx,bx,es>    ; Restore register(s).
  317.         ret                             ; Return to caller.
  318. ENDP    AsciiHexToBin
  319.  
  320. ;===============================================================
  321. ; Procedure:    =*=AsciiDecToBin=*=
  322. ;---------------------------------------------------------------
  323. ; Usage:        Public - available to other asm files.
  324. ; Task:         Convert decimal digit string to 16-bit value.
  325. ; Input:        di = offset address of string.
  326. ; Output:       If decimal, ax = 16-bit value, cf = 0.
  327. ;               If not decimal, cf = 1, ax = 0.
  328. ;               If invalid digit, cf = 1, ax = 0FFFFh.
  329. ; Registers:    ax is changed.
  330. ;===============================================================
  331. PROC    AsciiDecToBin
  332.  
  333.         SaveRegs <es,bx,cx,dx,si>       ; Save modified register(s).
  334.  
  335.         smove   es, ds                  ; es = data segment.
  336.         mov     si, di                  ; si -> ascii string.
  337.         call    strLength               ; cx = length of string (# digits).
  338.         add     si, cx                  ; si -> NULL.
  339.         dec     si                      ; si -> last digit.
  340.         std                             ; Auto-decrement si.
  341.         lodsb                           ; al = '0'->'9', si->2nd last digit.
  342.         dec     cx                      ; cx = # digits - 1.
  343.         cmp     al, '0'                 ; al >= '0' ?
  344.         jb      @@NoDec                 ; No : Not decimal, end.
  345.         cmp     al, '9'                 ; al <= '9' ?
  346.         ja      @@NoDec                 ; No : Not decimal, end.
  347.  
  348. ;-----  String is decimal number.
  349.         xor     ah, ah                  ; Clear ah.
  350.         xor     dx, dx                  ; Clear dx.
  351.         mov     bx, 10                  ; bx = 10^1.
  352.         mov     [wordVal], 0000h        ; Clear [wordVal].
  353.         mov     [base], 10              ; Base must be in word variable.
  354.         sub     al, '0'                 ; Convert to integer 0->9.
  355.         or      [wordVal], ax           ; OR 1st (leftmost) digit onto var.
  356. @@Rpt1:
  357.         jcxz    @@Success               ; No need for loop if only 1 digit.
  358.         xor     ax, ax                  ; Clear ax.
  359.         lodsb                           ; al = [si], dec si.
  360.         cmp     al, '0'                 ; al >= '0' ?
  361.         jb      @@Inval                 ; No : Invalid digit, end.
  362.         cmp     al, '9'                 ; al <= '9' ?
  363.         ja      @@Inval                 ; No : Invalid digit, end.
  364.         sub     al, '0'                 ; Yes: al = 0 to 9.
  365.         mul     bx                      ; axdx = ax * bx(10^x).
  366.         or      dx, dx                  ; dx > 0 (number too large) ?
  367.         jnz     @@Inval                 ; Yes: Invalid number, end.
  368.         add     [wordVal], ax           ; [wordVal] = [wordVal] + ax.
  369.         jc      @@Inval                 ; Number too large (invalid), end.
  370.         mov     ax, bx                  ; ax = 10^x.
  371.         mul     [base]                  ; ax = 10^(x+1).
  372.         mov     bx, ax                  ; bx = 10^(x+1).
  373.         loop    @@Rpt1                  ; dec cx; If cx=0, exit loop.
  374. ;-----  Conversion complete.
  375. @@Success:
  376.         mov     ax, [wordVal]           ; ax = 16-bit value.
  377.         clc                             ; Reset carry flag.
  378.         jmp     NEAR    @@Return        ; End without error.
  379. @@NoDec:
  380.         xor     ax, ax                  ; ax = error code for 'not decimal'.
  381.         jmp     NEAR    @@Error
  382. @@Inval:
  383.         mov     ax, 0FFFFh              ; ax = 'invalid number' code.
  384. @@Error:
  385.         stc                             ; Set carry flag.
  386. @@Return:
  387.         RestoreRegs <si,dx,cx,bx,es>    ; Restore register(s).
  388.         ret                             ; Return to caller.
  389. ENDP    AsciiDecToBin
  390.  
  391.  
  392.         END             ; End of module.
  393.