home *** CD-ROM | disk | FTP | other *** search
- ; Library: ZSLIB
- ; Version: 3.6
- ; Module: MLWDC
- ; Version: 1.0
- ; Author: Gene Pizzetta
- ; Date: March 2, 1992
- ; Comment: Much modified from some ideas of David Cortesi.
- ;
- ; MLWDC -- stores 4-byte binary integer as up to 10 ASCII digits, with
- ; or without leading spaces, in a memory buffer of variable size.
- ;
- ; Entry: HL = address of 32-bit binary number (stored low-byte first)
- ; DE = address of memory buffer for output (10 byte minimum)
- ; A = minimum output field size (1 to size of memory buffer)
- ; Exit: DE = address of byte following output
- ; Uses: DE
- ; Notes: Memory buffer for output must be at least the same size as the
- ; field size given in A, with an 10 byte minimum. The ASCII
- ; number will be padded with leading spaces to the field size.
- ; If the converted number is longer than the given field size,
- ; the complete number will be output anyway.
- ;
- PUBLIC MLWDC
- ;
- MLWDC: push af ; save registers
- push bc
- push hl
- ld (FldSiz),a ; save field size
- ld (StrBuf),de ; save address of string output buffer
- ld bc,4 ; move copy of long-word to local buffer
- ld de,LWBuf ; ..to preserve original copy
- ldir
- xor a
- ex de,hl ; HL -> BCD buffer
- ld b,5 ; 5 bytes
- Fill: ld (hl),a ; null it out
- inc hl
- djnz Fill
- ld b,32 ; 32 bits to convert
- ; Shift long-word one bit left, high bit moving to carry flag
- Loop0: ld hl,LWBuf
- push bc ; save outer loop counter
- ld b,4 ; shift each of the four bytes
- LoopA: rl (hl)
- inc hl
- djnz LoopA
- ; Double 10-digit packed BCD number, adding bit in carry. BCD number
- ; stored high byte first.
- ld hl,BCDBuf+4 ; start with low byte
- ld b,5 ; repeat for all 5 bytes
- LoopB: ld a,(hl) ; get byte
- adc a,a ; double it
- daa ; decimal adjust it
- ld (hl),a ; store doubled byte
- dec hl ; point to next byte
- djnz LoopB
- pop bc ; restore outer loop counter
- djnz Loop0
- ld b,5 ; number of BCD bytes
- ; Unpack BCD digits to ASCII, backwards through BCD and ASCII buffers, from
- ; low byte to high byte. RRD moves successive BCD digits to low nibble of A.
- ld de,AscBuf+9 ; low-order ASCII digit
- ld hl,BCDBuf+4 ; low-order BCD byte
- ld a,'0' ; set high nibble of a digit
- Loop1: rrd ; low digit into A
- ld (de),a ; ..stored
- dec de ; point to next slot
- rrd ; high digit to A
- ld (de),a ; ..stored
- dec de ; point to next slot
- dec hl ; back up to next BCD byte
- djnz Loop1
- inc de ; DE -> last stored digit
- ex de,hl ; move pointer to HL
- ; HL points to leftmost ASCII digit. Scan right to first non-zero digit.
- ; Count of ASCII digits is in B (less 1, so the last digit will always be
- ; preserved, even if it's a zero).
- ld b,10-1 ; ASCII digit count in B
- ld a,'0' ; compare to ASCII '0'
- Loop2: cp (hl) ; zero?
- jr nz,Exit2 ; (no, we're through)
- inc hl ; increment pointer
- djnz Loop2
- Exit2: inc b ; correct count of digits
- ; HL points to first (leftmost) non-zero digit with counter in B. Move them
- ; to the user's buffer. If field size is less than or equal to the actual
- ; length, just move the number. If field size is greater, add spaces first.
- ld de,(StrBuf) ; point to output buffer
- ld c,b
- ld b,0 ; BC = length of number
- ld a,(FldSiz)
- sub c ; A = field size less number size
- jr c,NoSpc ; (number bigger than field)
- jr z,NoSpc ; (number equals field)
- ld b,a ; B = count of leading spaces needed
- ld a,' '
- SpLoop: ld (de),a ; put a space into output buffer
- inc de ; increment pointer
- djnz SpLoop
- ; BC = length of number, DE points to output buffer (after leading spaces),
- ; HL points to first byte of number. Move it to output buffer.
- NoSpc: ldir ; leaves DE pointing to byte after last
- pop hl ; restore registers
- pop bc
- pop af
- ret
- ;
- DSEG
- ;
- AscBuf: ds 10 ; work area for ASCII 10-digit number
- LWBuf: ds 4 ; work area for 4-byte long-word
- BCDBuf: ds 5 ; work area for 5-byte packed BCD number
- FldSiz: ds 1 ; storage for field size
- StrBuf: ds 2 ; output buffer address
- ;
- end