Fwd: some useful features

ZXNet echo conference «code.zx»

From Kirill Frolov To Kirill Frolov 6 July 2003

- --- begin of forward --- From: Kirill Frolov Newsgroups: zxnet.code Subject: some useful features Date: Sun, 6 Jul 2003 08:07:24 +0000 (UTC) Press RESET immediately, All! Some spektrumists asked the question about generation random numbers and tabular calculation of CRC... General notes for everyone presented functions. ---------------------------------- Any functions unless otherwise specified specifically, do not guarantee safety any microprocessor registers except registers I and IY. Features marked guaranteed to be C compiler safe ensure the safety of register IX. All functions unless otherwise noted specifically, are reentrant, in other words allow nested or recursive calls, and do not use static variables or self-modifying collapsing code. All variables are highlighted are on the stack. Number conversion functions: ------------------------------ htoa The function writes unsigned number specified in register A to the string specified by the HL register in hexadecimal Reckoning. 2 will be recorded digits (leading zero present) vuet) and the symbol with code 0 is completed reading a line. Upon completion function register HL will indicate call on the last character of the line ki (terminating 0). wtoaThe function writes an unsigned the number specified in the BC register to the string specified by the HL register in the decimal number system. Leading zeros are not recorded. Up to 6 bytes can be written, including the symbol with code 0 completed reading a line. In HL register returns a pointer to the after- Day character of the line (code 0). Functions for working with strings: ------------------------------ strglob The function performs a comparison string specified by the HL register with mask string of the specified region stroma DE. In case the line corresponds to the mask flag Z will be installed. The mask can consist of any characters (except the character with code 0). Some symbols are interpreted in a special way: * -- means any number any symbols. ? -- means any one symbol. Math functions: ------------------------------ mul The function multiplies the unknown The original 16-bit numbers are given in registers DE and BC, and placed stores the result in the DE registers and H.L. The DE register stores the old The lowest bits of the result. Function you- completes in approximately 800 clock cycles processor. See also descriptionamul function. amul The function multiplies unsigned High numbers specified in registers A and DE and adds the result to the contents of the HL register. Function runs faster than mul, in about 350 cycles and maybe be used to access to array elements. In that case tea if the dimensions of the elements or array dimensions are multiples of 2^n or are constants maybe be more profitable to use more other ways to accelerate smart marriage. In case it is required faster access to elements arrays of arbitrary size element or dimension can be appropriate to use Aylifa massifs. div The function divides a given number in the HL register to the number specified in the BC register, the result is placed is entered into the HL register, and the remainder to register DE. In case of division is written to 0 in the HL register zero, and in the DE register the value divisible. The function is running in about 900 cycles. sqrt The function calculates the integer square root value from an unsigned number given nogo in the HL register, the result returned in register A. w2bcdThe function converts unsigned 16-bit number in binary but-decimal format. Argument is specified in the HL register, the result is tat is returned in registers D, E and C. The most significant bits of the result are they are contained in register D, low in register C. randn The function returns pseudo-cases tea number in a given range no. Minimum return value the random number being specified is 0. The maximum is always less than the number specified in the DE register. Result tat is returned in the HL register. See also function description rand. rand The function returns unsigned pseudorandom number in register H.L. The returned number is in the range 0..65535. Function runs a little faster functions randn. Execution of functions tion rand in time approximately equals 3 calls to the mul function, while runtime randn functions are comparable to 4 calls to the mul function. srand The function sets the generator torus of random numbers. When installing vke generator with one value generated sequence there will be pseudorandom numbers always repeat. Functions for calculating control codes:------------------------------------- flatcher The function calculates the values Fletcher code. In register IX a pointer to the area is passed memory, the contents of which calculation will be made. In re- size is transferred to the BC hyster memory areas in bytes. In registers HL and DE return 16-bit values are available Fletcher code. It's not too much good feature for control data integrity, but works faster than the CCC calculation functions. crc16_init The function initializes the table for quick counting 16-bit cyclic excess code (CEC) with the crc16_fast function. The de register contains the address 512 byte memory for saving the calculated table. The BC register indicates the threshold giving a CEC polynomial. In telecom communication protocols using recommended by the CCITT value: #1021. crc16_fast The function calculates the value CEC for the memory area from the beginning address specified in the register IX and length in bytes specified in BC register. In the DE register the re- the address of the preliminary table is given exactly calculated using functions crc16_init. In the registerHL indicates the initial value tion of the Central Election Commission. The result will be calculated is returned in the HL register. crc16 The function calculates the value CEC for the memory area from the beginning address specified in the register IX and length in bytes specified in BC register. In the DE register, called the generating polynomial Central Election Commission. In the HL register it is set to initial value of the CEC. Result calculation returns to the register str HL. As a generative CEC polynomial in telecommunications cation protocols uses- this is the CCITT recommended value #1021. The result of this function is the execution is completely similar to crc16_fast function, however this function does not use infection her calculated table and time her work is much larger. It is recommended to use the function tions crc16_init and crc16_fast, if you need to count CEC of large data volumes.

From Kirill Frolov To Kirill Frolov 6 July 2003

- --- beginning of forward --- From: Kirill Frolov Newsgroups: zxnet.code Subject: нетоторые пункциы Date: Sun, 6 Jul 2003 08:07:24 +0000 (UTC) [...subject..subject. ifndef htoa ifused htoa ; a=0..FF, HL=str[3] -> hl=*0 htoa push off rra rra rra rra call nib2hex pop off nib2hex and #0f cp #0a sbc a, #69 daily ld (hl), a inc hl ld (hl), ret endif endif ifndef string globe ifused string globe ; hl=string, de=mask -> Z strglob ld a, (de) or a jr nz, strglob_1 cpi ; end ret strglob_0 xor a inc a ret strglob_1 ld a, (hl) or a jr z, strglob_0 ; not equal ld a, (de) cp "?" jr z, strglob_q cp "*" jr z , strglob_a cp (hl) ret nz ; not equal strglob_q inc hl inc of jr strglob strglob_a inc hl push hl push there call strglob pop there pop hl ret z inc of jr strglob endif endif ifused wtoa ifndef wtoa ; slightly less than 16-year-old snowflakes; in decimal form, leading zeros are not discarded. ; 5 digits of the number will be written to address (hl) and ; character with code 0 ending the line. ; (C) Kirill Frolov ; *hl = itoa(de) -> hl=pointer to terminating 0. wtoa push hl ex de, hl call w2bcd pop hl ; d,e,c=bcd ld a, d or a jr nz, wtoa0 ld a, e and #f0 jr nz, wtoa1 ld a, e and #0f jr nz, wtoa2 ld a, c and #f0 jr nz, wtoa3 jr wtoa4 wtoa0 or #30 ld (hl), a inc hl wtoa1 ld (hl), e ld a, #33 rrd inc hl wtoa2 or #30 ld (hl), a inc hl wtoa3 ld (hl), c ld a, #33 rrd inc hl wtoa4 or #30 ld (hl), a inc hl ld (hl), 0 ret endif endif ifused rand ; Random number generator, slow ; (C) Kirill Frolov ~3000 takts. ; hl = random(0.. hl = random number 0..65535 ~2300 takts. rand; randx = randx*1103515245 + 12345)>>16) & 077777) ld de, (randx+2) ld bc, #4e6d call mul push hl ld de, (randx) ld bc, #41c6 call mul pop de add hl, de push hl ld de, (randx) ld bc, #4e6d call mul ld bc, #3039 add hl, bc ld (randx), hl pop hl adc hl, de ld (randx+2), hl ret endif ifused srand ; Installing a random number generator ; de = trigger value srand ld (randx), de ret endif ifused div ifndef div ; 16-bit unsigned division function ; (C) Aleksey Malov aka Vivid ; little optimized by Vitaly Vidmirov ; hl = de/bc de = de%bc ~840 takts. ; hl = 0, de = de(dividend) if bc(divisor) == 0. div xor a ;change sign subc ; at the divider ld c, a sbc a, b sub c ld b, a ld hl,0 ;reset the new dividend to zero ld a,d ;move first rla ;high byte of dividend ;t=18 REPT 8 rl l ; add hl,bc ; jr c,$+4 ;8 times sbc hl,bc ; rla ; t=8*45=360 ENDR ld d,a ;st. result byte ld a,e ;now move rla ;low byte t=12REPT adc hl,hl ; add hl,bc ; jr c,$+4 ;8 months sbc hl,bc ; rla ; t=8*52=4 ENDR ld e,a ;мл. байт результата ;hl-view of the делеия ;t=4 ex of, hl ret endif endif ifused mul ifndef mul ; you can get a 16-year-old boy ; (C) Kirill Frolov ; idea by Vasil Ivanov ; dehl=de*bc ~730h. mul ld hl, ld a, c ld c, l ; 18 add a, a jr nc, $+4 add hl, there adc a, c ; 29 rept add hl, hl rla jr nc, $+4 add hl, there adc a, c ; 40*7 309 endr ld c, a push hl ; 0chl ld hl, ld a, b ld b, l ; 33 add a, a jr nc, $+4 add hl, there add a, b ; 29 rept add hl, hl rla jr nc, $+4 add hl, there add a, b ; 40*7 309 endr ; ahl0 + 0cde = hlde pop there ld b, l ld l, h ld h, a ld a, d add a, b ld d, a ld b, adc hl, bc ex there, hl ; 60 ret ; 729t. endif endif ifused amul ifndef amul; 8-bit multiply-sum function ; (C) Kirill Frolov ; hl = hl + a*de ~338 takts. amul add a, a jr nc, $+4 add hl, de adc a, c ; 39 rept 7 add hl, hl rla jr nc, $+4 add hl, de adc a, c ; 40*7 309 endr ret endif endif ifused sqrt ifndef sqrt ; function for calculating the square root of 16-bit numbers ; (C) Aleksey Malov aka Vivid ; a = sqrt(hl) ~470 takts. sqrt xor a ;zeroed a ;-) ld de,64 ;this is required by the algorithm ; t=14 sla h ;take the two leftmost adc a,a ;argument bit sla h; adc a,a ; jr z,$+4 ;if they are not equal dec a ;zero, then increase inc d ;result ; t=39 REPT 3 sla h;follow adc a,a ;extraction algorithm sla h ;square root adc a,a ;"column", only sla d ; ld c,d ;3 times sli c ; cp c ; jr c,$+4 ; subc ; inc d; t=63*3=189 ENDR REPT 2 sla l ;we do something similar adc a,a ;operation with sla l ;low byte adc a,a ;argument sla d ;ld c,d ;2 times sli c ; cp c ; jr c,$+4 ; subc ; inc d; t=63*2=126 ENDR ld h,a ; or a ;cleared the carry flag ; t=8 sbc hl,de ;now we lack jr nc,$+3 ;one register d for add hl,de ;execute the last ccf ;two cycles, will have to rl d ;use more add hl,hl ;slow operations add hl,hl ;with register pairs ; t=67 sbc hl,de ;and last time ccf ;perform calculations, not ld a,d ;restoring hl adc a,a ;in a-result ; t=27 ret endif endif ifused w2bcd ifndef w2bcd ; function translates 16-bit unsigned ; binary number to BCD format ; (C) Kirill Frolov ; d,e,c = bin2bcd(hl) ~1330 takts. w2bcd ld b, 10h xor a ld c, a ld e, a ld d, a ; 23 w2bcd0 add hl, hl ; D,E,C=bcd digits ld a, c adc a, a yeah ld c, a ld a, e adc a, a yeah ld e, a ld a, d adc a, a yeah ld d,a djnz w2bcd0 ; ~83 ~1328 ret endif endif ; Attention!; All 16-bit CEC counting functions ; use only shift left! ifused flatcher ; Fletcher code counting function ; (faster, but less efficient than CRC) ; (C) Kirill Frolov ; ix=data, bc=size, ; -> hl=fletcher code (A), de=(B), E&L=8bit code flatcher ldhl,0 ld e, l ld d, h flatch0 ld a, b or c ex de, hl ret z ex de, hl ld a, (ix) inc ix add a, e ld e, a jr nc, $+3 inc d add hl, de dec bc jr flatch0 endif ifused crc16_init ; A function that initializes the CRC table. ; (C) Kirill Frolov ; de=table location address (512 bytes), ; bc=polynomial (0x1021 recommended by CCITT). crc16_init push ix ld xl, e inc d inc d ld xh, d ld e, c ld d, b ld c, 0 crc_i0 ld l, 0 ld h, c dec h ld b, 8 crc_i1 add hl, hl jr nc,crc_i2 ld a, l xor e ld l, a ld a, h xor d ld h, a crc_i2 djnz crc_i1 Dec ix ld (ix+0), l dec xh ld (ix+0), h inc xh dec c jr nz, crc_i0 pop ix ret endif ifused crc16_fast; fast (tabular) CRC-16 counting function, ; requires initialization with crc16_init function ; (C) Kirill Frolov ; ix=*data, bc=size, ; de=CRC table, hl=initial value ; on output -> hl=calculated value crc16_fast push de exx pop de exx crc16f0 ld a, b or c ret z ld a, h xor (ix) inc ix exx ld l, a ld h, 0 adc hl, de ld a, (hl) inc h exx xor l ld h, a exx ld a, (hl) exx ld l, a dec bc jr crc16f0 endif ifused crc16 ; slow CRC-16 counting function ; (C) Kirill Frolov ; ix=*data, bc=size ; de=polynomial (#1021), hl=initial value ; on output -> hl=calculated value crc16 crc16_0 ld a, b or c ret z ld a, (ix) inc ix xor h ld h, a ld a, 8 crc16_1 add hl, hl jr nc, crc16_2 exa ld a, l xor e ld l, a ld a, h xor d ld h, a exa crc16_2 dec a jr nz, crc16_1 dec bc jr crc16_0 endif - --- end of forward ---

From Kirill Frolov To Kirill Frolov 6 July 2003

- --- beginning of forward --- From: Kirill Frolov Newsgroups: zxnet.code Subject: нетоторые пункциы Date: Sun, 6 Jul 2003 08:07:24 +0000 (UTC) [...subject..subject. ifndef htoa ifused htoa ; a=0..FF, HL=str[3] -> hl=*0 htoa push off rra rra rra rra call nib2hex pop off nib2hex and #0f cp #0a sbc a, #69 daily ld (hl), a inc hl ld (hl), ret endif endif ifndef string globe ifused string globe ; hl=string, de=mask -> Z strglob ld a, (de) or a jr nz, strglob_1 cpi ; end ret strglob_0 xor a inc a ret strglob_1 ld a, (hl) or a jr z, strglob_0 ; not equal ld a, (de) cp "?" jr z, strglob_q cp "*" jr z , strglob_a cp (hl) ret nz ; not equal strglob_q inc hl inc of jr strglob strglob_a inc hl push hl push there call strglob pop there pop hl ret z inc of jr strglob endif endif ifused wtoa ifndef wtoa ; slightly less than 16-year-old snowflakes; in decimal form, leading zeros are not discarded. ; 5 digits of the number will be written to address (hl) and ; character with code 0 ending the line. ; (C) Kirill Frolov ; *hl = itoa(de) -> hl=pointer to terminating 0. wtoa push hl ex de, hl call w2bcd pop hl ; d,e,c=bcd ld a, d or a jr nz, wtoa0 ld a, e and #f0 jr nz, wtoa1 ld a, e and #0f jr nz, wtoa2 ld a, c and #f0 jr nz, wtoa3 jr wtoa4 wtoa0 or #30 ld (hl), a inc hl wtoa1 ld (hl), e ld a, #33 rrd inc hl wtoa2 or #30 ld (hl), a inc hl wtoa3 ld (hl), c ld a, #33 rrd inc hl wtoa4 or #30 ld (hl), a inc hl ld (hl), 0 ret endif endif ifused rand ; Random number generator, slow ; (C) Kirill Frolov ~3000 takts. ; hl = random(0.. hl = random number 0..65535 ~2300 takts. rand; randx = randx*1103515245 + 12345)>>16) & 077777) ld de, (randx+2) ld bc, #4e6d call mul push hl ld de, (randx) ld bc, #41c6 call mul pop de add hl, de push hl ld de, (randx) ld bc, #4e6d call mul ld bc, #3039 add hl, bc ld (randx), hl pop hl adc hl, de ld (randx+2), hl ret endif ifused srand ; Installing a random number generator ; de = trigger value srand ld (randx), de ret endif ifused div ifndef div ; 16-bit unsigned division function ; (C) Aleksey Malov aka Vivid ; little optimized by Vitaly Vidmirov ; hl = de/bc de = de%bc ~840 takts. ; hl = 0, de = de(dividend) if bc(divisor) == 0. div xor a ;change sign subc ; at the divider ld c, a sbc a, b sub c ld b, a ld hl,0 ;reset the new dividend to zero ld a,d ;move first rla ;high byte of dividend ;t=18 REPT 8 rl l ; add hl,bc ; jr c,$+4 ;8 times sbc hl,bc ; rla ; t=8*45=360 ENDR ld d,a ;st. result byte ld a,e ;now move rla ;low byte t=12REPT adc hl,hl ; add hl,bc ; jr c,$+4 ;8 months sbc hl,bc ; rla ; t=8*52=4 ENDR ld e,a ;мл. байт результата ;hl-view of the делеия ;t=4 ex of, hl ret endif endif ifused mul ifndef mul ; you can get a 16-year-old boy ; (C) Kirill Frolov ; idea by Vasil Ivanov ; dehl=de*bc ~730h. mul ld hl, ld a, c ld c, l ; 18 add a, a jr nc, $+4 add hl, there adc a, c ; 29 rept add hl, hl rla jr nc, $+4 add hl, there adc a, c ; 40*7 309 endr ld c, a push hl ; 0chl ld hl, ld a, b ld b, l ; 33 add a, a jr nc, $+4 add hl, there add a, b ; 29 rept add hl, hl rla jr nc, $+4 add hl, there add a, b ; 40*7 309 endr ; ahl0 + 0cde = hlde pop there ld b, l ld l, h ld h, a ld a, d add a, b ld d, a ld b, adc hl, bc ex there, hl ; 60 ret ; 729t. endif endif ifused amul ifndef amul; 8-bit multiply-sum function ; (C) Kirill Frolov ; hl = hl + a*de ~338 takts. amul add a, a jr nc, $+4 add hl, de adc a, c ; 39 rept 7 add hl, hl rla jr nc, $+4 add hl, de adc a, c ; 40*7 309 endr ret endif endif ifused sqrt ifndef sqrt ; function for calculating the square root of 16-bit numbers ; (C) Aleksey Malov aka Vivid ; a = sqrt(hl) ~470 takts. sqrt xor a ;zeroed a ;-) ld de,64 ;this is required by the algorithm ; t=14 sla h ;take the two leftmost adc a,a ;argument bit sla h; adc a,a ; jr z,$+4 ;if they are not equal dec a ;zero, then increase inc d ;result ; t=39 REPT 3 sla h;follow adc a,a ;extraction algorithm sla h ;square root adc a,a ;"column", only sla d ; ld c,d ;3 times sli c ; cp c ; jr c,$+4 ; subc ; inc d ; t=63*3=189 ENDR REPT 2 sla l ;we do something similar adc a,a ;operation with sla l ;low byte adc a,a ;argument sla d ;ld c,d ;2 times sli c ; cp c ; jr c,$+4 ; subc ; inc d; t=63*2=126 ENDR ld h,a ; or a ;cleared the carry flag ; t=8 sbc hl,de ;now we lack jr nc,$+3 ;one register d for add hl,de ;execute the last ccf ;two cycles, will have to rl d ;use more add hl,hl ;slow operations add hl,hl ;with register pairs ; t=67 sbc hl,de ;and last time ccf ;perform calculations, not ld a,d ;restoring hl adc a,a ;in a-result ; t=27 ret endif endif ifused w2bcd ifndef w2bcd ; function translates 16-bit unsigned ; binary number to BCD format ; (C) Kirill Frolov ; d,e,c = bin2bcd(hl) ~1330 takts. w2bcd ld b, 10h xor a ld c, a ld e, a ld d, a ; 23 w2bcd0 add hl, hl ; D,E,C=bcd digits ld a, c adc a, a yeah ld c, a ld a, e adc a, a yeah ld e, a ld a, d adc a, a yeah ld d,a djnz w2bcd0 ; ~83 ~1328 ret endif endif ; Attention!; All 16-bit CEC counting functions ; use only shift left! ifused flatcher ; Fletcher code counting function ; (faster, but less efficient than CRC) ; (C) Kirill Frolov ; ix=data, bc=size, ; -> hl=fletcher code (A), de=(B), E&L=8bit code flatcher ldhl,0 ld e, l ld d, h flatch0 ld a, b or c ex de, hl ret z ex de, hl ld a, (ix) inc ix add a, e ld e, a jr nc, $+3 inc d add hl, de dec bc jr flatch0 endif ifused crc16_init ; A function that initializes the CRC table. ; (C) Kirill Frolov ; de=table location address (512 bytes), ; bc=polynomial (0x1021 recommended by CCITT). crc16_init push ix ld xl, e inc d inc d ld xh, d ld e, c ld d, b ld c, 0 crc_i0 ld l, 0 ld h, c dec h ld b, 8 crc_i1 add hl, hl jr nc,crc_i2 ld a, l xor e ld l, a ld a, h xor d ld h, a crc_i2 djnz crc_i1 Dec ix ld (ix+0), l dec xh ld (ix+0), h inc xh dec c jr nz, crc_i0 pop ix ret endif ifused crc16_fast; fast (tabular) CRC-16 counting function, ; requires initialization with crc16_init function ; (C) Kirill Frolov ; ix=*data, bc=size, ; de=CRC table, hl=initial value ; on output -> hl=calculated value crc16_fast push de exx pop de exx crc16f0 ld a, b or c ret z ld a, h xor (ix) inc ix exx ld l, a ld h, 0 adc hl, de ld a, (hl) inc h exx xor l ld h, a exx ld a, (hl) exx ld l, a dec bc jr crc16f0 endif ifused crc16 ; slow CRC-16 counting function ; (C) Kirill Frolov ; ix=*data, bc=size ; de=polynomial (#1021), hl=initial value ; on output -> hl=calculated value crc16 crc16_0 ld a, b or c ret z ld a, (ix) inc ix xor h ld h, a ld a, 8 crc16_1 add hl, hl jr nc, crc16_2 exa ld a, l xor e ld l, a ld a, h xor d ld h, a exa crc16_2 dec a jr nz, crc16_1 dec bc jr crc16_0 endif - --- end of forward ---

From Vlad Sotnikov To Kirill Frolov 8 July 2003

Hello, Kirill! July 6, 2003 (it was 12:08 then) Kirill Frolov in his letter to Kirill Frolov wrote: KF> Some spectromists asked the question about generation KF> random numbers and tabular calculation of CRC... Some spectromists :) Vega/ex-Style Group. FIDO: 2:5030/1512 ZXNET: 500:812/19 E-mail: vega56@mail.ru

From Pavel Vasilyev To Kirill Frolov 8 July 2003

Hello Kirill! Sunday, 06 July 2003, at 12:09:19, Kirill Frolov -> Kirill Frolov. KF> ; function translates 16-bit unsigned KF> ; binary number to BCD KF> ; (C) Kirill Frolov KF> ; d,e,c = bin2bcd(hl) ~1330 takts. KF> w2bcd KF> ld b, 10h KF> xor a KF> ld c, a KF> ld e, a KF> ld d, a ; 23 KF> w2bcd0 KF> add hl, hl ; D,E,C=bcd digits KF> ld a, c KF> adc a, a KF> daa KF> ld c, a KF> ld a, e KF> adc a, a KF> daa KF> ld e, a KF> ld a, d KF> adc a, a KF> daa KF> ld d, a KF> djnz w2bcd0 ; ~83 ~1328 KF> retw2bcd ld bc,#1000: ld e,c w2bcd0 add hl,hl ld a,c: adc a,a: daa: ld c,a ld a,e: adc a,a: daa: ld e,a rl d: djnz w2bcd0 ret ; b=18 ; t=1043 Close the door behind me, Kirill, I'm leaving.