; Library: ZSLIB ; Version: 3.6 ; Module: PLWDC ; Version: 1.0 ; Author: Gene Pizzetta ; Date: March 6, 1992 ; Comment: Much modified from some ideas of David Cortesi. ; ; PLWDC -- prints 4-byte binary integer as up to 10 ASCII digits, with or ; without leading spaces. ; ; Entry: HL = address of 32-bit binary number (stored low-byte first) ; A = minimum output field size (1-255) ; Exit: None, number is printed. ; Uses: None. ; Notes: 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 PLWDC ; EXT COUT ; SYSLIB ; PLWDC: push af ; save all registers push bc push de push hl ld (FldSiz),a ; save field size 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. If field ; size is less than or equal to the actual length, just output number. If ; field size is greater, output spaces first. 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: call COUT ; output leading spaces djnz SpLoop ; C = length of number, HL points to first byte of number, so output it. NoSpc: ld b,c ; put count in B NmLoop: ld a,(hl) call COUT inc hl djnz NmLoop pop hl ; restore all registers pop de 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 ; end