%%HP: T(3)A(R)F(.); "CODE NB4BT EQU 2 nibbles per 1 byte MAXRO EQU 15 nejdelsi je MMMDCCCLXXXVIII *===============================* * VSTUPNI BOD * *===============================* C=DAT1 A C(A): adresa objektu na RPL-stacku ?C#0 A je platna? GOYES RO_ARG - ano, pokracovat LA(5) #201 - ne, chybove hlaseni *Too Few Arguments* RO_ERROR GOVLNG =Errjmp RO_ERROR_VAL GOSBVL =GETPTR LA(5) =argvalerr chybove hlaseni *Bad Argument Value* GOTO RO_ERROR *===============================* * NA STACKU JE ARGUMENT * *===============================* RO_ARG CD1EX D1: adresa objektu A=DAT1 A A(A): prolog D1=C D1: adresa objektu vracena LC(5) =DOINT ?A=C A je to ZINT? GOYES RO_A2R - ano LC(5) =DOCSTR ?A#C A je to STRING? GOYES + - ne GOTO RO_R2A - ano + LA(5) =argtypeerr chybove hlaseni *Bad Argument Type* GOTO RO_ERROR *===============================* * JE TO CISLO * *===============================* * R0(A): docasna pamet pro vysledek * R1(A): pointer na cifry (vychozi D1) * R2(A): index aktualni cifry (dekadicky rad) * R3(A): pointer na tabulku rimskych cislic sromt[] * B(A): index do tabulky sromt[] * D1SROMT MACRO C=R3.F A C(A): sromt[] C=C+B A B(A): index podle dekadickeho radu D1=C D1: sromt[] + index D1SROMT ENDM * RO_A2R GOSUB RO_START * D1: pointer na cifry * C(A): pocet cifer C=C-1 A pouze nula ma jen jeden nibble ?C=0 A je to nula? GOYES RO_ERROR_VAL - ano AD1EX A(A): adresa hodnoty A=A+C A A(A): adresa posledniho nibble... D1=A D1: ...tam kam patri A=DAT1 P A(0): znamenko ?A#0 P je to minus? GOYES RO_ERROR_VAL - ano C=C-CON A,5 moc velky pocet znaku? GONC RO_ERROR_VAL - ano D1=D1- 1 D1: pointer na prvni cifru (MSD) C=C+1 A ctyrmistne cislo? (C=C-5+1 -> C=C-1) GONC + - ne, bez kontroly A=DAT1 P A(0): prvni cifra A=A-CON P,4 hodnota > 3999? GONC RO_ERROR_VAL - ano + C=C+CON A,3 C(A): pocet cifer - 1 R2=C.F A R2(A): index prvni cifry (MSD) LC(5) (MAXRO)*(NB4BT) GOSUB RO_A2R_MEM AD0EX A(A): docasna pamet pro vysledek R0=A.F A AD0EX C=R2.F A C(A): index prvni cifry (MSD) C=C+C A viz. NB4BT C=C+C A 2 rimske cislice na kazdy dekadicky rad B=C A B(A): index do tabulky sromt[] GOSUB RO_SROMT R3(A): sromt[] *-------------------------------* * ZPRACOVANI JEDNE CIFRY * *-------------------------------* RO_A2R_LOOP A=DAT1 P A(0): cifra AD1EX R1=A.F A R1(A): pointer na cifry AD1EX A(0): cifra LC(1) 4 ?A=C P je to 4? GOYES RO_A2R_4_9 - ano LC(1) 9 ?A#C P je to 9? GOYES RO_A2R_REST0 - ne RO_A2R_4_9 D1SROMT C=DAT1 B z sromt[]... DAT0=C B ...do vysledku D0=D0+ NB4BT dalsi znak ve vysledku D1=D1+ NB4BT dalsi znak v sromt[] A=A+A P byla to 9? GONC + - ne D1=D1+ NB4BT - ano, dalsi znak v sromt[] + C=DAT1 B z sromt[]... DAT0=C B ...do vysledku D0=D0+ NB4BT dalsi znaku ve vysledku GOTO RO_A2R_CONT RO_A2R_REST1 D1SROMT LC(1) 5 ?A byte A=R1.F A z R1... D1=A ...obnovit D1 RTN *===============================* * JE TO RETEZEC * *===============================* * R0(A): _IDX * R1(0): _INC (1 nebo 5) * R2(A): delka zadani (uschova C) * R3(A): pointer na tabulku rimskych cislic sromt[] * R4(A): pocet stejnych nebo mensich predchozich rimskych cislic * D(0): prechozi _IDX * D0: pointer na addt[] + subt[] * D1: pointer na znaky (zadani) * C2ORD MICRO CSRB.F P C(A): _ORD * RO_R2A GOSUB RO_START CSRB.F A # nibble -> byte * D1: pointer na znaky * C(A): pocet znaku C=C-1 A LA(5) MAXRO ?C>=A A prilis dlouhe nebo kratke zadani? GOYES RO_R2A_ERROR R2=C.F A R2(A): pocet znaku GOSUB RO_SROMT R3(A): sromt[] LC(5) 2*5 C(A): delka addt[] + subt[] GOSUB RO_A2R_MEM D0: pointer na addt[] + subt[] * C=0 A Vynulovat: R4=C A - pocet stejnych nebo mensich DAT0=C A - addt[] D0=D0+ 5 DAT0=C A - subt[] D0=D0- 5 D0: pointer na addt[] + subt[] * C=C-1 A C(A): 0xFFFFF D=C A D(0): prechozi _IDX *-------------------------------* * ZPRACOVANI JEDNOHO ZNAKU * *-------------------------------* RO_R2A_LOOP AD0EX A(A): pointer na addt[] + subt[] C=R3.F A D0=C D0: sromt[] C=DAT1 B B=C B B(B): znak ze zadani D0=D0- NB4BT - D0=D0+ NB4BT dalsi znak v sromt[] C=DAT0 B C(B): znak z tabulky sromt[] ?C#0 B tabulka pokracuje? GOYES + - ano RO_R2A_ERROR GOTO RO_ERROR_VAL + ?C#B B znaky zadani:tabulka jsou ruzne? GOYES - - ano AD0EX D0: pointer na addt[] + subt[] * A(A): adresa nalezu v sromt[] C=R3.F A C(A): sromt[] A=A-C A A(A): rozdil pointeru ASRB.F A # nibble -> byte == _IDX R0=A.F A R0(A): _IDX LC(1) #1 maska A=A&C P A(0): _WHT A=A+A P A=A+A P A(0): _WHT << 2 A=A+1 P R1=A.F P R1(0): _INC * A=0 A A(A): smask C=R0.F A C(A): _IDX ?C= prechozi _IDX? GOYES + - ne, smask: 0 A=A-1 A - ano, smask: -1 + C=R4 A C(A): less C=C-A A C(A): less - smask C=C&A A C(A): less - smask & smask R4=C A R4(A): nova hodnota less C=C-CON A,3 less > 3? GONC RO_R2A_ERROR - ano * C=R0.F A C(A): _IDX ?C<=D A aktualni _IDX <= prechozi _IDX GOYES RO_R2A_SUMM - ano *-------------------------------* * AKTUALNI > PREDCHOZI * *-------------------------------* C=R4 A C(A): less C=C-CON A,2 less >= 2? GONC RO_R2A_ERROR - ano * C=D A C(A): prechozi _IDX C2ORD C(A): _ORD AD0EX D0=A A(A): addt[] A=A+C A A(A): addt[] + _ORD AD0EX A(A): addt[] C=DAT0 P D0: addt[] + _ORD B=C P B(0): addt[_ORD] C=0 P DAT0=C P addt[_ORD] = 0 D0=D0+ 5 D0: subt[] + _ORD C=B P C(0): addt[_ORD] DAT0=C P subt[_ORD] = addt[_ORD] AD0EX D0: addt[] C=R0.F A C(A): _IDX *-------------------------------* * PRICTENI AKTUALNI HODNOTY * *-------------------------------* RO_R2A_SUMM D=C A D(A): nove prechozi _IDX C2ORD C(A): _ORD AD0EX D0=A A(A): addt[] A=A+C A A(A): addt[] + _ORD AD0EX D0: addt[] + _ORD C=DAT0 P B=C P C(0): addt[_ORD] C=R1.F P C=C+B P C(0): addt[_ORD] + _INC DAT0=C P AD0EX D0: pointer na addt[] + subt[] C=C+CON P,6 prirustek stejneho radu v norme? GONC + - ano GOTO RO_R2A_ERROR + C=R2.F A C(A): zbyvajici pocet znaku C=C-1 A jeste nejake znaky ze zadani? GOC + - ne, hotovo R2=C.F A D1=D1+ NB4BT dalsi znak ze zadani GOTO RO_R2A_LOOP - ano, pokracovat + *-------------------------------* * VYSLEDEK A JEHO DELKA * *-------------------------------* A=DAT0 A cely obsah addt[] D0=D0+ 5 C=DAT0 A cely obsah subt[] SETDEC A=A-C A A(A): vysledek! SETHEX LC(5) #10000 B=C A LC(5) 5 - BSR A C=C-1 P ?A