Код:
;----------------------------------------;
;Printing in Different Evaluation Systems;
; LIBrary v2.0 ;
; (c) SerzhSoft, Shadrinsk, august, 1997 ;
;----------------------------------------;
_NULL EQU 0 ;Используется в изменяемых командах
;----------------------------------------;
; print in DEC system: ;
;----------------------------------------;
PDEC_3B ;Печать десятичного числа в AHL (00000000..16777215)
LD DE,34464 ;DE=100000-65536
LD BC,#FF01 ;B=-1 - счетчик сотен тысяч; С=1
LP_PD31 INC B ;увеличиваем счетчик сотен тысяч
AND A ;сбрасываем флаг переноса для SUB
SBC HL,DE ;уменьшаем трехбайтное число AHL
SBC A,C ;на одну сотню тысяч
JR NC,LP_PD31 ;повторяем пока нет переполнения
ADD HL,DE ;восстанавливаем положительное
ADC A,C ;значение у AHL; AHL<100000
PUSH AF ;сохраняем на стеке нужные нам
PUSH HL ;впоследствии регистры A, HL
LD A,B ;количество сотен тысяч в числе
CALL PDEC_B ;печатаем это значение
POP HL ;восстанавливаем со стека
POP AF ;регистры A, HL
DEC A ;если остаток<65536,
JR NZ,PDEC_W ;то переходим на печать 0..65535
LD DE,5536 ;иначе - число 65536..99999
ADD HL,DE ;прибавляем остаток от десятков
ADC A,B ;тысяч, и их сами - отдельно
PUSH HL ;------------------------------------
LD HL,DECTB_W ;Обходимый фрагмент процедуры PDEC_W
LD B,#05 ;------------------------------------
JR LP_PDW1+1 ;прыжок через обнуление десятков тысяч
;---------------------------------------------------------------------
PDEC_B ;Печать десятичного числа в A (000..255)
LD L,A ;поместили
LD H,#00 ; число в HL
PUSH HL ;закинули печатаемое число на стек
LD HL,DECTB_W+4 ;адрес в таблице, начиная с сотни
LD B,#03 ;максимальное возможное количество цифр - три
JR LP_PDW1 ;переход на цикл печати
;---------------------------------------------------------------------
PDEC_W ;Печать десятичного числа в HL (00000..65535)
PUSH HL ;закинули печатаемое число на стек
LD HL,DECTB_W ;адрес таблицы степеней десятки
LD B,#05 ;максимальное возможное количество цифр
LP_PDW1 XOR A ;обнулили счетчик и флаг C для SBC
LD E,(HL) ;взяли текущую степень
INC HL ; десятки из таблицы
LD D,(HL) ; и поместили в DE
INC HL ;перешли к следующему элементу таблицы
EX (SP),HL ;адрес элемента <-> печатаемое число
LP_PDW2 INC A ;увеличиваем счетчик
SBC HL,DE ;вычитаем текущую степень десятки
JR NC,LP_PDW2 ;повторяем пока HL>=0
ADD HL,DE ;HL=HL mod DE; A=HL div DE
ADD A,"0"-1 ;перевод A в ASCII-код ("0".."9")
RST #10 ;печать десятичной цифры
EX (SP),HL ;HL=адрес элемента, число -> на стек
DJNZ LP_PDW1 ;цикл по цифрам
POP HL ;убрали оставшийся ноль со стека
RET ;выход из процедуры
;---------------------------------------------------------------------
DECTB_W DW 10000,1000,100,10,1 ;Таблица степеней десятки
;----------------------------------------;
; print in HEX system: ;
;----------------------------------------;
PHEX_W ;Печать шестнадцатиричного числа в HL (0000..FFFF)
LD A,H ;печать старшего байта числа
CALL PHEX_B ;вызов процедуры HEX-печати байта
LD A,L ;печать младшего байта числа
;---------------------------------------------------------------------
PHEX_B ;Печать шестнадцатиричного числа в A (00..FF)
CALL PHEX_HB ;печатать по полубайтам
;---------------------------------------------------------------------
PHEX_HB ;Печать старшего полубайта в A (0..F)
RRCA ;меняем
RRCA ; местами
RRCA ; старший
RRCA ; и младший полубайты
;---------------------------------------------------------------------
PHEX_LB ;Печать младшего полубайта в A (0..F)
PUSH AF ;сохранили A на стеке
AND #0F ;отбросили лишние старшие биты
CP #0A ;если A<10,
JR C,GO_PHL ; то перепрыгнули
ADD A,"A"-"9"-1 ;корректировка: после "9" идет "A"
GO_PHL ADD A,"0" ;перевод в ASCII-код
RST #10 ;печать HEX-цифры ("0".."F")
POP AF ;восстановили A со стека
RET ;выход из процедуры
;----------------------------------------;
; print in BIN system: ;
;----------------------------------------;
PBIN_W ;Печать двоичного числа в HL (16 разрядов 0/1)
LD A,H ;печть старшего байта числа
CALL PBIN_B ;вызов процедуры BIN-печати байта
LD A,L ;печть младшего байта числа
;---------------------------------------------------------------------
PBIN_B ;Печать двоичного числа в A (8 рязрядов 0/1)
LD B,#08 ;в байте - 8 битов
LP_PBB RLCA ;поочередно 'выдвигаем' биты в CF
PUSH AF ;сохранить A на стеке
LD A,#18 ;в зависимости от флага C:
RLA ;A="0" или A="1"
RST #10 ;печать очередного бита
POP AF ;восстановить A со стека
DJNZ LP_PBB ;поразрядный цикл
RET ;выход из процедуры
;----------------------------------------;
; print in USER system: ;
;----------------------------------------;
PUSE_W ;Печать числа в установленной MKUSETB системе счисления в HL
PUSH HL ;закинули печатаемое число на стек
HL_PUW LD HL,_NULL ;адрес конца таблицы степеней
LP_PUW1 DEC HL ;загружаем в DE очередную
LD D,(HL) ; степень числа
DEC HL ; из таблицы
LD E,(HL) ; двигаясь сверху-вниз
EX (SP),HL ;адрес таблицы <-> печатаемое число
XOR A ;обнуление A и сброс флага C
LP_PUW2 INC A ;вычисляем очередной
SBC HL,DE ; разряд числа и результат
JR NC,LP_PUW2 ; помещаем в A (A=1+(HL div DE))
ADD HL,DE ;восстанавливаем положительное значение
ADD A,"0"-1 ;переводим A в ASCII-код
CP "9"+1 ;если код меньше "9",
JR C,GO_PUW1 ; то переход на печать
ADD A,"A"-"9"-1 ;коррекция (после "9" идет "A")
GO_PUW1 RST #10 ;печать очередной цифры числа
EX (SP),HL ;HL=адрес таблицы, число -> стек
DEC DE ;если степень
LD A,D ; числа не равна единице
OR E ; (самый первый элемент таблицы),
JR NZ,LP_PUW1 ; то продолжаем работу
POP HL ;убираем со стека ненужный 0
RET ;выход из процедуры
;---------------------------------------------------------------------
MKUSETB ;Создание таблицы степеней с основанием в A
LD HL,USE_TBL ;адрес создаваемой таблицы
LD DE,#0001 ;инициализация счетчика степени
LP_MUT1 LD (HL),E ;запись текущего
INC HL ; значения степени
LD (HL),D ; в таблицу и переход
INC HL ; к ее следующей ячейке
PUSH HL ;сохраняем адрес на стеке
LD B,A ;основание степени -> в счетчик цикла
LD HL,#0000 ;обнуление результата
LP_MUT2 ADD HL,DE ;подсчитываем результат
JR C,GO_MUT ;если HL>65535, то прерываем счет
DJNZ LP_MUT2 ;повторяем <основание> раз
EX DE,HL ;результат - в DE (новая степень)
GO_MUT POP HL ;восстанавливаем адрес таблицы
JR NC,LP_MUT1 ;если не прерывались, то повторяем
LD (HL_PUW+1),HL ;адрес конца таблицы -> в PUSE_W
RET ;выход из процедуры
;---------------------------------------------------------------------
USE_TBL DS 32 ;Таблица степеней текущей системы счисления
;----------------------------------------;
; print in RIM system: ;
;----------------------------------------;
PRIM_B ;Печать числа в римской записи в A (I..CCLV)
LD L,A ;скопировать
LD H,#00 ; A в HL
;---------------------------------------------------------------------
PRIM_W ;Печать числа в римской записи в HL (I..MMMCMXCIX)
PUSH HL ;закинули печатаемое число на стек
LD HL,RIM_TBL ;адрес таблицы знаков
DB #DD ;работаем с половинкой регистра IX
LD L,#07 ;LD XL, число знаков в римском счислении
LP_PRW1 LD E,(HL) ;считываем из таблицы значение
INC HL ; очередного знака римской системы
LD D,(HL) ; счисления и помещаем в DE
INC HL ;затем в регистр C считываем
LD C,(HL) ; ASCII-код знака
INC HL ;переход к следующему знаку
LD (HL_PRW+1),HL ;сохранили адрес следующего знака
EX (SP),HL ;адрес -> на стек, HL=печатаемое число
XOR A ;обнуление счетчика и сброс CF
LP_PRW2 INC A ;в цикле производим
SBC HL,DE ; деление HL на DE (вычитаем,
JR NC,LP_PRW2 ; пока нет переполнения)
ADD HL,DE ;восстанавливаем положительное значение
DEC A ;т.к. A на 1 больше HL div DE,
JR Z,GO_PRW1 ; то если A=1 - ничего не печатаем
LD B,A ;количество печатаемых символов
LP_PRW3 LD A,C ;код знака
RST #10 ;печатаем его
DJNZ LP_PRW3 ;сколько надо - столько и печатаем
GO_PRW1 DB #DD ;работаем с половинкой регистра IX
LD A,L ;LD A,XL - номер текущего знака
DEC A ;если это последний знак (I), то
JR Z,GO_PRW4 ; двухбуквенного сочетания нет
EX (SP),HL ;HL=адрес следующего знака, число -> стек
RRA ;если номер текущего знака четный,
JR C,GO_PRW2 ; то сочетание с следующим знаком,
INC HL ; иначе - перепрыгнуть через один
INC HL ; знак. В результате получим адрес
INC HL ; знака, для получения двойного
GO_PRW2 LD A,C ; знакосочетания (IV, CM, XL...)
LD C,(HL) ; взяли из таблицы значение для
INC HL ; этого знака и получили
LD B,(HL) ; разность между значением
INC HL ; основного и этим значением.
EX DE,HL ; Например, для основного знака X
AND A ; дополнительным будет I, а их
SBC HL,BC ; разность соответственно:
EX DE,HL ; 10-1=9, т.е. IX
LD C,A ;код основного знака
LD A,(HL) ;код дополнительного знака
EX (SP),HL ;HL=печатаемое число
SBC HL,DE ;если оно < дополнительного
JR C,GO_PRW3 ; значения, то не печатаем
RST #10 ;печать дополнительного знака
LD A,C ;основной знак
RST #10 ;печать
JR GO_PRW4 ;результат - двухбуквенное сочетание
GO_PRW3 ADD HL,DE ;восстановили (+) у числа
GO_PRW4 EX (SP),HL ;число -> на стек
HL_PRW LD HL,_NULL ;адрес следующего знака в таблице
DB #DD ;работаем с половинкой регистра IX
DEC L ;DEC XL - уменьшаем счетчик знаков
JR NZ,LP_PRW1 ;крутим цикл пока есть еще знаки
POP HL ;сняли ненужный уже ноль со стека
RET ;выход из процедуры
;---------------------------------------------------------------------
RIM_TBL ;Таблица значимости букв в написании римских чисел
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 50
DB "L" ;L=50 ;XL=40
DW 10
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.0 ;
;----------------------------------------;