;********************************************* ; násobení 16b x 16b bez znaménka - výsledek 32b ; superrychlá - 54 cykly procesoru ; rozsah kodu (8051) - 50 byte ;********************************************* ; kontrola na nulu násobitele nebo násobence ; není nutná !! (pouze pro skrácení času) ; - max 15 cyklů procesoru, rozsah kódu - 18 byte ; dobu exekuce mul16x16 zvětší o max 9 cyklů ;********************************************* ;vstup v ren3 je bajt_H a ren2 je bajt_L násobence - m1 ; v ren5 je bajt_H a ren4 je bajt_L násobitele - m2 ;v ren 5 je tedy m2H, v ren4 - m2L,v ren3 - m1H a v ren2 -m1L ; ;výstup v ren5 je 4_byte a ren4 je 3_byte ; v ren3 je 2_byte a ren2 je 1_byte ; v popisu označíme výsledek res po bajtech res4..res1 ;v ren 5 je tedy res4, v ren4 - res3,v ren3 - res2 a v ren2 -res1 ; mění reg.: Acc,ren2,ren3,ren4,ren5,Psw ; možnost zvolit si prac. registry ren2 equ r2 ren3 equ r3 ren4 equ r4 ren5 equ r5 ;******* mul16x16k: clr a cjne ren5,#0,mul16x16 ;kontrola m2H na 0 cjne ren4,#0,mul16x16e ;kontrola m2L na 0 mov ren2,a ;0 -> m1L mov ren3,a ;0 -> m1H mul16x16e: cjne ren3,#0,mul16x16 ;kontrola m1H na 0 cjne ren2,#0,mul16x16 ;kontrola m1L na 0 mov ren4,a ;0 -> m2L mov ren5,a ;0 -> m2H ret ;******* mul16x16: push B mov a,ren5 ;musí odložit m2H push acc mov a,ren2 ;m1L do acc mov b,ren4 ;m2L do B mul ab ;násobí m1L* m2L xch a,ren2 ;res1 do ren2 ,m1L do acc xch a,b ;do b m1L, res2 do acc xch a,ren5 ;res2 do ren5 , m2H do acc mul ab ;násobí m2H*m1L add a,ren5 ;připočítá res2 xch a,ren4 ;res2 do ren4 , m2L do acc xch a,b ;m2L do b, res3 do acc addc a,#0 ;zohledni přenos z 2_B do 3 mov f0,C ;zapamatuje přenos z 3_B do 4 xch a,ren3 ;res3 do ren3 , m1H do acc mov ren5,a ;m1H odloží do ren5 mul ab ;násobí m1H*m2L add a,ren4 ;připočítá předch. výsled v res2 xch a,ren3 ;res2 do ren3 , res3 do acc addc a,b ;připočítá novy mezivýsledek ku res3 xch a,ren5 ;m1H do acc , res3 do ren5 mov b,a ;m1H do b clr a rlc a ;přenos do 4-bajtu mov C,f0 addc a,#0 ;přenos do 4-bajtu mov ren4,a ;ulozi res4 do ren4 pop acc ;m2H do acc mul ab ;násobí m1H*m2H add a,ren5 ;připecte res3 xch a,ren4 ;res3 do ren4 , res4 do acc addc a,b mov ren5,a ;výsledek 4_bajt pop b ret ;*******
Prvním úkonem podprogramu musí samozřejmě býti kontrola na dělení nulou !! Opět, zvolením si vhodné posloupnosti matematických úkonů, nebudeme potřebovat další pomocné registry (kromě obligátních: Acc a B). |
;********************************************* ; dělení 16b / 16b bez znaménka ;doba exekuce - min 7 cyklů pro div by 0 ; - w/w max 39 cyklů ; - w/B max 143 cyklů ; - B/B max 27 cyklů ; - průměr 70 cyklů ; rozsah kódu (8051) - 93 byte ;********************************************* ;vstup v DH je bajt_H a DL je bajt_L dělence ;vstup v dih je bajt_H a dil je bajt_L dělitele ;výstup Cy =1 pro div by 0, jinak Cy =0 a ; v DH je bajt_H a DL je bajt_L - zbytku ; v dih je bajt_H a dil je bajt_L - podílu ; ; mění reg.: Acc,DH,DL,dH,dL,b,Psw ; možnost zvolit si prac. registry***** DH equ r3 DL equ r2 dih equ r5 dil equ r4 ;******* div16x16: cjne dih,#0,divAA cjne dil,#0,divBA setb C ret ;divide by 0 divAA: mov a,DH mov b,dih div ab jnz divAB ;výsledek ma H_bajt mov dih,a mov dil,a ret ;divide finalized, result=0 divAB: push b ;odlož zbytek mov DH,a ;ulož vysl_L do rp mov b,dil mul ab xch a,DL subb a,DL xch a,DL pop acc subb a,b jnc divABcont dec DH xch a,DL add a,dil xch a,DL addc a,dih clr C divABcont: xch a,DH mov dil,a mov dih,#0 ret ;divide finalized divBA: mov b,dil mov a,DH div ab mov dih,a ;ulož H_podíl mov DH,b cjne DH,#0,divBB mov b,dil mov a,DL div ab mov dil,a mov DL,b ret divBB: mov DH,#8 divBB1: mov a,DL rlc a mov DL,a mov a,dil xch a,b rlc a jc divBB2 div ab rrc a djnz DH,divBB1 mov a,b xch a,DL ;zbytek do DL, do acc mezivysl_L rlc a mov dil,a ret divBB2: clr C subb a,b mov b,a djnz DH,divBB1 mov a,b xch a,DL ;zbytek do DL, do acc mezivysl_L rlc a mov dil,a ret ;*******
;********************************************* ; konverze BCD -> bin rozsah čísla do 99 999 (65 535) ; superrychlá - 69 cyklu (max), 54(min) ; rozsah kodu (8051) - 72 byte ;********************************************* ;vstup v re3 je tis_sta a re2 je des_jed ; v acc desítky tisíc ;vystup v re3 je udaj_H a re2 je udaj_L ; ; mění reg.: Acc,re2,re3,psw ; možnost zvolit prac registry****** re2 equ r2 re3 equ r3 ;******* bcd_bin: push B push acc ;desítky tisíc do stacku mov a,re2 anl a,#0F0H ;desítky swap a mov b,#10D mul ab ;n2*0AH xch a,re2 anl a,#0FH ;jednotky add a,re2 mov re2,a ;desítky a jednotky spolu bin mov b,#100D mov a,re3 anl a,#0FH ;stovky mul ab ;n3*64H add a,re2 ;připočti k průběžnému výsledku mov re2,a clr a addc a,b xch a,re3 anl a,#0F0H ;tisíce -> acc swap a mov b,a ;tisíce -> b add a,acc ;acc * 2 add a,b ;spolu acc = 3* tisíce add a,re3 ;připočti k průběžnému výsledku mov re3,a mov a,#0E8H ;L_byte of 03E8H=1000D mul ab ;n4*0E8H add a,re2 ;připočti k průběžnému výsledku mov re2,a mov a,b addc a,re3 mov re3,a pop acc ;obnoví desítky_tisíc ze stacku jz converBCDbin_end mov b,a ;desítky_tisíc -> b swap a ;násobeni* 10H - L_byte čísla 2710H=10000D add a,re2 mov re2,a clr a ;přenos C addc a,re3 mov re3,a mov a,#27H ;H_byte čísla 2710H=10000D mul ab ;n5*27H add a,re3 ;připočti k průběžnému výsledku mov re3,a orl C,b.0 ;carry pro čísla > 65 535 converBCDbin_end: pop b ret ;*******
;********************************************* ; konverze BCD -> bin rozsah čísla do 99 999 (65 535) ; superrychlá - 69 cyklu (max), 54(min) ; rozsah kodu (8051) - 72 byte ;********************************************* ;vstup v re3 je tis_sta a re2 je des_jed ; v acc desítky tisíc ;vystup v re3 je udaj_H a re2 je udaj_L ; ; mění reg.: Acc,re2,re3,psw ; možnost zvolit prac registry****** re2 equ r2 re3 equ r3 ;******* bcd_bin: push B push acc ;desítky tisíc do stacku mov a,re2 anl a,#0F0H ;desítky swap a mov b,#10D mul ab ;n2*0AH xch a,re2 anl a,#0FH ;jednotky add a,re2 mov re2,a ;desítky a jednotky spolu bin mov b,#100D mov a,re3 anl a,#0FH ;stovky mul ab ;n3*64H add a,re2 ;připočti k průběžnému výsledku mov re2,a clr a addc a,b xch a,re3 anl a,#0F0H ;tisíce -> acc swap a mov b,a ;tisíce -> b add a,acc ;acc * 2 add a,b ;spolu acc = 3* tisíce add a,re3 ;připočti k průběžnému výsledku mov re3,a mov a,#0E8H ;L_byte of 03E8H=1000D mul ab ;n4*0E8H add a,re2 ;připočti k průběžnému výsledku mov re2,a mov a,b addc a,re3 mov re3,a pop acc ;obnoví desítky_tisíc ze stacku jz converBCDbin_end mov b,a ;desítky_tisíc -> b swap a ;násobeni* 10H - L_byte čísla 2710H=10000D add a,re2 mov re2,a clr a ;přenos C addc a,re3 mov re3,a mov a,#27H ;H_byte čísla 2710H=10000D mul ab ;n5*27H add a,re3 ;připočti k průběžnému výsledku mov re3,a orl C,b.0 ;carry pro čísla > 65 535 converBCDbin_end: pop b ret ;*******
;********************************************* ; konverze bin -> BCD pro rozsah čísla do to 131 071 ; superrychlá - průměr 85 cyklů procesoru ; max 100 cyklů procesoru ; velkost kodu - 77 byte ;********************************************* ;vstup v re3 je udaj_H a re2 je udaj_L ; v Cy je bit b17 - v bin formatu ;vystup v re3 je tis_sta a re2 je des_jed ; v acc stovky_tisíc a desítky_tisíc- v BCD formatu ; ; mění reg.: Acc,re2,re3, psw ; možnost zvolit prac registry****** re2 equ r2 re3 equ r3 ;******* bin_bc16: clr C bin_bc17: push B ;store content of B mov a,re3 rrc a ;to divide re3 with 2 = to shift one right xch a,re2 ;re2->acc, re3/2 ->re2 rrc a ;to divide re2 with 2, b0 re2->C mov f0,C ;bit0 from re2 in f0 xch a,re2 ;re2/2->re2 , re3/2->acc clr C rrc a ;to divide re3/2 with 2 = to shift one right xch a,re2 ;re2/2->acc, re3/4 ->re2 rrc a ;to divide re2/2 with 2, b1 re2->C push psw ;store b1 re2 in Cy xch a,re2 ;re3/4->acc, re2/4 ->re2 mov re3,a ;re3/4 -> re3 corre4: mov b,#06H mul ab add a,re2 ;to add re2/4 mov re2,a ;store result xch a,b ;byte_H ->acc , byte_L -> b addc a,#0H jz corre1 xch a,r3 add a,re3 ;final count of thousands xch a,re3 ;final count of thousands -> re3,bajt_H ->acc sjmp corre4 corre1: mov a,#25D ;will to divide 250 = 100/4 xch a,b ;b->25D,remainder of divide 1000D -> acc div ab ;in acc hundreds , in b remainder cjne a,#10D,corre2 clr a inc re3 corre2: mov re2,a ;count of hundreds -> re2 mov a,#10D ;for tens xch a,b ;b->10D,remainder of divide 100D -> acc pop psw ;restore b1 of re2 in Cy rlc a mov C,f0 ;to multiply by 4 and to comlete rlc a ;stored bits div ab swap a orl a,b ;BCD tens and units -> acc xch a,re3 ;acc -> re3,final count of thousands -> acc mov b,#10D ;for calculate tenththousands div ab ;in acc tenththousands , in b thousands xch a,b ; acc <-> b swap a ;thousands into H_nibble orl a,re2 ;BCD thousands and hundreds -> acc xch a,re3 ;BCD tens and units -> acc,BCD thousands_hundreds -> re3 mov re2,a ;BCD tens and units -> re2 mov a,b ;stored tenththousands into Acc add a,#0 da a ;tenththousands into BCD pop b ;rebuilt of reg b ret
;********************************************* ; součet 16b + 16b - result 16b ; rychlý - 8 cycklů processoru ; kód - 7 byte ;********************************************* ;Vstup v ren3 je byte_H , ren2 je byte_L prvního sčítance -m1 ; v ren5 je byte_H , ren4 je byte_L druhého sčítance -m2 ; tj.:v ren 5 je m2H, v ren4 - m2L, ren3 - m1H , ren2 -m1L ; ;výstup v ren5 je byte_H , ren4 je byte_L součtu ;v příznaku Cy může být přetečení ; mění reg.: Acc,re4,re5, psw ; možnost zvolit prac registry****** ren2 equ r2 ren3 equ r3 ren4 equ r4 ren5 equ r5 ;******* add16to16: xch a,ren4 ;m2L <-> acc add a,ren2 xch a,ren5 ;m2H <-> result of Lbytes sum addc a,ren3 xch a,ren5 ;result of Lbytes sum <-> result of Hbytes sum xch a,ren4 ;acc <-> result of Lbytes sum ret ;*******
Analogicky jakou součet. ;********************************************* ; rozdíl 16b + 16b - result 16b ; rychlý - 9 cycklů processoru ; kód - 8 byte ;********************************************* ;Vstup: v ren3 je byte_H , ren2 je byte_L odčítance -m1 ; v ren5 je byte_H , ren4 je byte_L odčítatele -m2 ; tj.:v ren 5 je m2H, v ren4 - m2L, ren3 - m1H , ren2 -m1L ; ;výstup: v ren5 je byte_H , ren4 je byte_L rozdílu ;v příznaku Cy může být přetečení, v příznaku OV - znaménko ; mění reg.: Acc,re4,re5, psw ; možnost zvolit prac registry****** ren2 equ r2 ren3 equ r3 ren4 equ r4 ren5 equ r5 ;******* sub16to16: xch a,ren4 ;m2L <-> acc clr C ;necessarily subb a,ren2 xch a,ren5 ;m2H <-> result of Lbytes odds subb a,ren3 xch a,ren5 ;result of Lbytes odds <-> result of Hbytes odds xch a,ren4 ;acc <-> result of Lbytes odds ret ;*******
;************************************** ;inverze znaku b7b6...b1b0 na b0b1..b6b7 ;**************************************** ; vstup - rei, vystup - rei ; mění registry: Acc, psw a rei ; možnost zvolit prac registr********** rei equ r3 inverze: mov a,#01H ;ve funkci počítadla x8 inverze1: ;pro posuv doleva xch a,rei ;acc <-> rei rrc a xch a,rei ;acc <-> rei rlc a jnc inverze1 xch a,rei ;výsledek -> rei ret ;*******Tento způsob úspory počítadla můžeme použít vždy, je-li počet opakování 8 a současně v těle smyčky máme posuv o jeden bit. Další aplikací této "finty" může býti sériový příjem (vyslání) byte.
© DH servis 2002 - |