reader-reader - Print numbers in different number systems.

ZX Review #7-8-9-10
(C) Kolotov Sergei g.Shadrinsk,
SerzhSoft, V, 1997.


    PRINT NUMBERS IN DIFFERENT

       Radix


   One of the most important computer tasks is to derive the 
numbers screen (printing). Where the numbers

can be presented in various
number systems, of which there are not so little.

   The most familiar of all
We, of course, is a decimal system, ie system
radix base 10. Ten here appears no accident: the man from 
ancient times believed the finger hands, as they are known - 
ten. But the computer "habitual" assumed to be in the decimal 
system, and in binary, because all the information in it is the 
electric charges: is the current (1) and no current (0). So how 
do translated from "a computer" language to normal man?


   The following procedure prints the numbers given
register A (accumulator) in decimal form. Printing to a 
standard command RST # 10 in the current output stream. The 
length of the procedure, 23 bytes. In its work, she uses a 
3-byte table of ten degrees, and if

performance, in a series of counts and the number of prints
hundred (first digit), tens of
(Second) and units (third digit)
numbers.


   See Listing 1.


   Yet it is unlikely that
and not be a need
print, say, in hexadecimal or binary systems
notation. Yes, even in the same
decimal, but, for example, numbers
the range is not between 0 and 255, and from
0 to 65535. Therefore, it suffices
advisable to always "have a
hand "library of procedures
intended for printing numbers in a variety of systems
notation, in various
ranges. What me and realized ...


   See Listing 2.


   The composition of the library
includes procedures for the printing of numbers in a variety of 
systems notation. Namely: decimal,

hex, binary, set by the user (eg, octal) and, as
particularly exotic, the system Roman numbers.

   Procedures that make up the library, have much in common, and
fully understand the one,
can more quickly grasp the
principle of the rest. All
print headlines procedures begin with the P (Print). Further 
there are three letters that define a system in which the 
number of prints. Then separated underscore character, you 
should one of the symbols B and W, define a range of printed 
numbers: Byte (Byte), or the word (Word). In the first case (B) 
before calling the procedure, the number should be in the 
register A (accumulator), and in the second case (W) - in the 
register pair HL. Printing is the current output stream 
(command RST # 10). 


  Library description PDES LIB


   1. Print decimal


   1) The procedure PDEC_W - print

      numbers in the results
      gistrovoy pair HL. Range
      Zones print: 00000 .. 65535.

      The length of the procedure, 26 bytes.

      Uses a table of degree
      It tens DECTB_W.

   2) Procedure PDEC_B - print

      the number of A (000 .. 255), 10

      bytes. In his work vyzy
      Vaeth PDEC_W.

   3) Table DECTB_W - contains

      5 degrees of scores given by
      GOVERNMENTAL as words (2 bytes) -

      length of 10 bytes.


   Total length of section: 10 10 26

   = 46 bytes.


   2. Print hex

               numbers


   1) Pr-pa PHEX_LB - printing ml.

      nibble in A (0 .. F), 14

      bytes.

   2) Pr-pa PHEX_HB - print art.

      nibble in A (0 .. F), 4

      bytes. Swaps on
      lubayty A and causes

      PHEX_LB.

   3) Pr-pa PHEX_B - print number
      la in A (00 .. FF), 3 bytes.

      Two times is PHEX_HB.

   4) Pr-pa PHEX_W - print number
      la in the HL (0000 .. FFFF), 5

      bytes. Two times is

      PHEX_B.


   Total length of section: 5 +3 +4 14

   = 26 bytes.


     3. Print binary numbers


   1) Pr-pa PBIN_B - print number
      la in A (8 bits), 12

      bytes.

   2) Pr-pa PBIN_W - print number
      la in HL (16 bits), 5

      bytes. Two times is

      PBIN_B.


   Total length of section: 5 +12 = 17

   bytes.

4. Print numbers in radix set by the user.


   Served as a prototype for the procedure, published in an 
excellent reference - book Rodionova

and A. Larchenko "ZX-Spectrum for
users and programmers. "


   1) Pr-pa MKUSETB - filling

      Table degrees USE_TBL with

      grounds specified in the active
      kumulyatore. The length of the pr-algebra 28

      bytes.

   2) Pr-pa PUSE_W - print number
      la in HL. Uses previously

      created MKUSETB table

      degrees USE_TBL. 33 bye
      Ta.

   3) Table USE_TBL - Table

      degrees, 32 bytes.


   Total length of section: 32 33 28

   = 93 bytes.


    5. Printing Roman numerals


   1) Pr-pa PRIM_W - print number
      la in the HL (I.. MMMCMXCIX), 77

      bytes. Uses a table

      RIM_TBL.

   2) Pr-pa PRIM_B - print number
      la in A (I.. CCLV). Length 3



      bytes. Calls the procedure

      PRIM_W.

   3) Table RIM_TBL - Table

      significance of letters in napisa
      Institute of Roman numerals. Length:

      7 * 3 = 21 bytes.


   Total length of section: 21 3 77

   = 101 bytes.


   Full size libraries: 283

   bytes.
140.
Listing 1. The printing process bytes in decimal.

PDEC_B; print a decimal number to akkumulyatore3 (000 .. 255)

        LD HL, DECTB_B; address table tens of degrees

        LD B, # 03; max. possible number of digits
LP_PDB1 LD C, "0" -1; initialize counter
LP_PDB2 INC C; increments

        SUB (HL); subtract the current level of tens of

        JR NC, LP_PDB2; repeat until A> = 0

        ADD A, (HL); A = A mod (HL); C = STR $ (A div (HL))

        PUSH AF; keep A on the stack

        LD A, C; the current figure

        RST # 10; print figures

        POP AF; restore battery

        INC HL; move to the next. tens of degrees

        DJNZ LP_PDB1; twisted loop on the numbers

        RET; exit procedures
;
DECTB_B DB 100,10,1; Table stepeney3 10-ki for a byte


Listing 2. Library of print in different number systems.

;------ PDES LIB -----; Printing in Different Evaluation 
Systems LIBrary ; (C) SerzhSoft, Shadrinsk, V, March 1997

;
_NULL EQU 0; used in changing teams
;
; --- Print in DEC system -;
PDEC_B; print a decimal number to A3 (000 .. 255)

        LD L, A; placed

        LD H, # 00; the number of HL

        LD DE, DECTB_W +4; address in the table, starting with 
hundreds of 

        LD B, # 03; max. possible number of digits - three

        JR LP_PDW1; go to print cycle
;
PDEC_W; print a decimal number in HL3 (00000 .. 65535)

        PUSH HL; threw the printed number on the stack

        LD HL, DECTB_W; address table tens of degrees

        LD B, # 05; max. possible number of digits
LP_PDW1 LD E, (HL); took the current degree of

        INC HL; dozens of tables

        LD D, (HL); and placed in DE

        INC HL; moved on to trace. element table

        EX (SP), HL; your e-ma <-> prints the number of

        XOR A; reset the counter and a flag C for SBC
LP_PDW2 INC A; increments

        SBC HL, DE; subtract the current level of tens of

        JR NC, LP_PDW2; repeat until HL> = 0

        ADD HL, DE; HL = HL mod DE; A = HL div DE

        ADD A, "0" -1; A translation into ASCII-code ("0" .. 
"9") 

        RST # 10; printing decimal numbers

        EX (SP), HL; HL = address of E-one number - "on the 
stack 

        DJNZ LP_PDW1; cycle by the numbers

        POP HL; removed the remainder of the zero from the stack

        RET; exit procedures
;
DECTB_W DW 10000,1000,100,10,1; Table of tens of degrees
;
; --- Print in HEX system -;
PHEX_W; Printing hexadecimal numbers in HL3 (0000 .. FFFF)

        LD A, H; print high byte of

        CALL PHEX_B; procedure call HEX-printing bytes

        LD A, L; print low byte of
;
PHEX_B; Print a hexadecimal number in A3 (00 .. FF)

        CALL PHEX_HB; print on nibble
;
PHEX_HB; print high-order nibble into A3 (0 .. F)

        RRCA; change

        RRCA; places

        RRCA; Senior

        RRCA; and minor nibbles
;
PHEX_LB; Print younger nibble into A3 (0 .. F)

        PUSH AF; saved on the stack A

        AND # 0F; threw extra high-order bits

        CP # 0A; if A <10,

        JR C, GO_PHL; then jumped

        ADD A, "A" - "9" -1; adjustment: after the "9" is "A"
GO_PHL ADD A, "0", translated into ASCII-code

        RST # 10; print HEX-digits ("0" .. "F")

        POP AF; A restored from the stack

        RET; exit procedures
;
; --- Print in BIN system -;
PBIN_W; print binary number to HL (16-bit 0 / 1)

        LD A, H; print high byte of

        CALL PBIN_B; procedure call BIN-printing bytes

        LD A, L; print low byte of
;
PBIN_B; print binary number in A (8 bits 0 / 1)

        LD B, # 08; in a byte - 8 bits
LP_PBB RLCA; alternately 'posit' bits in the CF

        PUSH AF; keep A on the stack

        LD A, # 18, depending on the flag C:

        RLA; A = "0" or A = "1"

        RST # 10; print the next bit

        POP AF; recover A from the stack

        DJNZ LP_PBB; bitwise cycle

        RET; exit procedures
;
; --- Print in USER system -;
PUSE_W; Seal of the installed system MKUSETB Acc-I in HL

        PUSH HL; threw the printed number on the stack
HL_PUW LD HL, _NULL; address of the end of the table of degrees
LP_PUW1 DEC HL; load at DE next

        LD D, (HL); degree of

        DEC HL; from the table,

        LD E, (HL); moving 'top-down'

        EX (SP), HL; address table <-> print-e number

        XOR A; A reset and reset the flag C
LP_PUW2 INC A; compute the next

        SBC HL, DE; digit numbers and the result

        JR NC, LP_PUW2; put it in A (A = 1 + (HL div DE))

        ADD HL, DE; restore (+) value

        ADD A, "0" -1; translating A in ASCII-code

        CP "9" +1, if the code is less than "9"

        JR C, GO_PUW1; then go to print

        ADD A, "A" - "9" -1; correction (after the "9" is "A")
GO_PUW1 RST # 10; print the next digit numbers

        EX (SP), HL; HL = address table, the number -> stack

        DEC DE; if the degree of

        LD A, D; numbers are not equal to unity

        OR E; (the very first entry in the table)

        JR NZ, LP_PUW1; work continues

        POP HL; remove waste from the stack 0

        RET; exit procedures
;
MKUSETB; Create a table of degrees with the base in A

        LD HL, USE_TBL; address to create tables

        LD DE, # 0001; initialization counter extent
LP_MUT1 LD (HL), E; record of current

        INC HL; the degree of

        LD (HL), D; to the table and the transition

        INC HL; to its next cell

        PUSH HL; store address on the stack

        LD B, A; founded th degree - "in the loop counter

        LD HL, # 0000 reset result
LP_MUT2 ADD HL, DE; calculate results

        JR C, GO_MUT; if HL> 65535, is interrupted by

        DJNZ LP_MUT2; repeat  times

        EX DE, HL; result - "in DE (new degree)
GO_MUT POP HL; restore the address table

        JR NC, LP_MUT1; if not interrupted, then repeat

        LD (HL_PUW +1), HL; address of the end of the table - 
"a PUSE_W 

        RET; exit procedures
;
USE_TBL DS 32; table degrees of the current number system
;
; --- Print in RIM system -;
PRIM_B; Print numbers in Roman records in A (I.. CCLV)

        LD L, A; copy

        LD H, # 00; A in HL
;
PRIM_W; Print numbers in Roman records in HL (I.. MMMCMXCIX)

        PUSH HL; threw the printed number on the stack

        LD HL, RIM_TBL; address table signs

        DB # DD; working with half of the register IX

        LD L, # 07; LD XL, the number of characters in p. radix
LP_PRW1 LD E, (HL); reads from the table value

        INC HL; another sign of the Roman system

        LD D, (HL); notation and place in DE

        INC HL; then read the register C

        LD C, (HL); ASCII-character code

        INC HL; the transition to the next character

        LD (HL_PRW +1), HL; store the address of the next 
character 

        EX (SP), HL; address -> on the stack, HL = printing. 
number 

        XOR A; reset counter and reset CF
LP_PRW2 INC A; in the cycle is

        SBC HL, DE; division of HL to DE (subtract,

        JR NC, LP_PRW2; no overflow)

        ADD HL, DE; restore (+) value

        DEC A; because A 1 more than HL div DE,

        JR Z, GO_PRW1; then if A = 1 - do not print

        LD B, A; the number of printed characters
LP_PRW3 LD A, C; character code

        RST # 10; print it

        DJNZ LP_PRW3; much need - so much, and print
GO_PRW1 DB # DD; working with half of the register IX

        LD A, L; LD A, XL - the current number of sign

        DEC A; if this is the last sign (I), then

        JR Z, GO_PRW4; two-letter combinations do not

        EX (SP), HL; HL = address of the trail. sign, the 
number-> stack 

        RRA; if the number of the current sign is even,

        JR C, GO_PRW2; the combination of the following 
characters 

        INC HL; otherwise - to jump over a

        INC HL; sign. As a result, we address

        INC HL; sign for double
GO_PRW2 LD A, C; symbol-strings (IV, CM, XL ...)

        LD C, (HL); taken from the table value for

        INC HL; this sign and got

        LD B, (HL); difference between the value

        INC HL; the ground and with this value.

        EX DE, HL; For example, the main sign of X

        AND A; extra will I, and their

        SBC HL, BC; difference, respectively:

140.

        EX DE, HL; 10-1 = 9, ie IX

        LD C, A; code of the main character

        LD A, (HL); code additional sign

        EX (SP), HL; HL = prints the number of

        SBC HL, DE; if it  on the stack
HL_PRW LD HL, _NULL; address of the next character in the table

        DB # DD; working with half of the register IX
        DEC L; DEC XL - decrement the counter of characters

        JR NZ, LP_PRW1; twist cycle, while there are still signs

        POP HL; removed unneeded already zero from the stack

        RET; exit procedures
;
RIM_TBL; Table significance of the letters in the writing of 
Roman numerals 

        DW 1000

        DB "M"; M = 1000; CM = 900

        DW 500

        DB "D"; D = 500; CD = 400

        DW 100

        DB "C"; C = 100; XC = 90

        DW 1950

        DB "L"; L = 50; XL = 40

        DW 1910

        DB "X"; X = 10; IX = 9

        DW 5

        DB "V"; V = 5; IV = 4

        DW 1

        DB "I"; I = 1;-nop;
; --- End of PDES LIB - 2

           *