AppleIIAsm-Collection/source/d7_convert/T.SUB.HEX2INTASC.ASM
2021-06-05 21:40:51 -04:00

116 lines
4.4 KiB
NASM

*``````````````````````````````*
* HEX2INTASC (NATHAN RIGGS) *
* *
* CONVERT A SIGNED HEXADECIMAL *
* VALUE TO AN INTEGER STRING. *
* *
* INPUT: *
* *
* ZPW1 = HEX TO CONVERT *
* *
* DESTROYS: NZCIDV *
* ^^^ ^ *
* *
* CYCLES: 268+ *
* SIZE: 157 *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
]NGFLAG EQU ZPW2 ; NEGATIVE FLAG
]VALSTR EQU ZPW1 ; HEXADECIMAL TO CONVERT
]MOD10 EQU ZPW3 ; VALUE MODULUS 10
*
HEX2INTASC
*
LDA ]VALSTR+1 ; {4C3B} STORE VALUE HIGH BYTE
STA ]NGFLAG ; {4C3B} IN THE NEGATIVE FLAG
BPL :GETBP ; {3C2B} IF VALUE IS POSITIVE, BRANCH
LDA #0 ; {3C2B} ELSE SUBTRACT LOW BYTE
SEC ; {2C1B}
SBC ]VALSTR ; {4C3B}
STA ]VALSTR ; {4C3B} STORE AS NEW LOW BYTE
LDA #0 ; {3C2B} ADJUST HIGH BYTE
SBC ]VALSTR+1 ; {4C3B}
STA ]VALSTR+1 ; {4C3B}
:GETBP
LDA #0 ; {3C2B} SET BUFFER TO EMPTY
LDY #0 ; {3C2B}
STA RETLEN,Y ; {5C2B} BUFFER(0) = 0
*
:CNVERT ; CONVERT VALUE TO STRING
LDA #0 ; {3C2B} RESET MODULUS
STA ]MOD10 ; {4C3B}
STA ]MOD10+1 ; {4C3B}
LDX #16 ; {4C3B}
CLC ; {2C1B} CLEAR CARRY
:DVLOOP
ROL ]VALSTR ; {7C3B} SHIFT CARRY INTO DIVBIT 0
ROL ]VALSTR+1 ; {7C3B} WHICH WILL BE THE QUOTIENT
ROL ]MOD10 ; {7C3B} + SHIFT DIV AT SAME TIME
ROL ]MOD10+1 ; {7C3B}
SEC ; {2C1B} SET CARRY
LDA ]MOD10 ; {4C3B} SUBTRACT #10 (DECIMAL) FROM
SBC #10 ; {4C3B} MODULUS 10
TAY ; {2C1B} SAVE LOW BYTE IN .Y
LDA ]MOD10+1 ; {4C3B} ADJUST HIGHBYTE
SBC #0 ; {4C3B} SUBTRACT CARRY
BCC :DECCNT ; {3C2B} IF DIVIDEND < DIVISOR, DEC CTR
STY ]MOD10 ; {4C3B} ELSE STORE RESULT IN MODULUS
STA ]MOD10+1 ; {4C3B} NEXT BIT OF QUOTIENT IS A 1,
; DIVIDEND = DIVIDEND - DIVISOR
:DECCNT
DEX ; {2C1B} DECREASE .X COUNTER
BNE :DVLOOP ; {3C2B} IF NOT 0, CONTINUE DIVIDING
ROL ]VALSTR ; {7C3B} ELSE SHIFT IN LAST CARRY
ROL ]VALSTR+1 ; {7C3B} FOR QUOTIENT
:CONCH
LDA ]MOD10 ; {4C3B}
CLC ; {2C1B} CLEAR CARRY
ADC #$B0 ; {4C3B} ADD '0' CHARACTER TO VALUE
; TO GET ACTUAL ASCII CHARACTER
JSR :CONCAT ; {6C3B} CONCATENATE TO STRING
*
** IF VALUE <> 0 THEN CONTINUE
*
LDA ]VALSTR ; {4C3B} IF VALUE STILL NOT 0,
ORA ]VALSTR+1 ; {7C3B} OR HIGH BIT, THEN KEEP DIVIDING
BNE :CNVERT ; {3C2B}
*
:EXIT
LDA ]NGFLAG ; {4C3B} IF NEGATIVE FLAG IS SET
BPL :POS ; {3C2B} TO ZERO, THEN NO SIGN NEEDED
LDA #173 ; {3C2B} ELSE PREPEND THE STRING
JSR :CONCAT ; {6C3B} WITH A MINUS SIGN
*
:POS ; VALUE IS POSITIVE
RTS ; {6C1B} RETLEN
*
:CONCAT ; STRING CONCATENATION SUBROUTINE
PHA ; {3C1B} SAVE CHAR ON STACK
*
** MOVE BUFFER RIGHT ONE CHAR
*
LDY #0 ; {3C2B} RESET INDEX
LDA RETLEN,Y ; {5C3B} GET CURRENT STRING LENGTH
TAY ; {2C1B} CURRENT LENGTH IS NOW INDEX
BEQ :EXITMR ; {3C2B} IF LENGTH = 0, EXIT CONCAT
*
:MVELP
LDA RETLEN,Y ; {5C3B} GET NEXT CHARACTER
INY ; {2C1B} INCREASE INDEX
STA RETLEN,Y ; {5C3B} STORE IT
DEY ; {2C1B} DECREASE INDEX BY 2
DEY ; {2C1B}
BNE :MVELP ; {3C2B} LOOP UNTIL INDEX IS 0
:EXITMR
PLA ; {3C1B} GET CHAR BACK FROM STACK
LDY #1 ; {4C3B}
STA RETLEN,Y ; {5C3B} STORE CHAR AS 1ST CHARACTER
LDY #0 ; {3C2B} RESET INDEX
LDA RETLEN,Y ; {5C3B} GET LENGTH BYTE
CLC ; {2C1B} CLEAR CARRY
ADC #1 ; {3C2B} INC LENGTH BY ONE
STA RETLEN,Y ; {5C3B} UPDATE LENGTH
*
LDA RETLEN ; {4C3B}
RTS ; {6C1B}