Vymenit deleni za nasobeni neni az tak trivialni jak muze vypadat.
Vetsinou ti podminky umozni to nasobit s dvojnasobnou sirkou.
A na konci to nekdy musis posouvat o par bitu doprava.
Vse kvuli zaokrouhleni.
Nedavno jsem cetl nejaky par let stary clanek, ktery ukazoval, ze ani nejlepsi prekladace nenajdou vzdy nejlepsi reseni. A vysvetloval nejake podminky, za kterych to jde udelat lepe.
Pisi jako hobby projekt prekladac pro Z80 a deleni konstanotou je... PEKLO. Vetsina veci kde se objevi konstanta je tezka, ale deleni je extrem. I modulo je lehci i kdyz jsem dlouho nevedel ze to jde delat bez deleni.
Metod na ktere jsem prisel jak udelat deleni je nekolik a kazda ma svoje podvarianty a ty nikdy nevis, ktery kod pujde nejlepe optimalizovat a bude nakonec nejlepsi.
Nasobit 6554? 16x16=32 bit...
To je zbytecne slozite (pokud procesor neumi nasobit).
U deleni 10 me nejlepe vychazi pouzit deleni 5. Protoze delit deseti je to same co "delit"dvema a pak deseti. Nebo naopak. Ale prvni se lepe optimalizuje, protoze mas uz zadarmo nasobek 2. Ktery vyuzijes protoze to prevadis na to nasobeni.
Deleni 5 se dela pres nasobeni 13107, ale drzi se to v 16x16=24 bit protoze se pouziva trik, ze ti staci to nasobit 51.
Osetrit zaokrouhleni.
A pak to vynasobit 257! 51*257=13107
A nasobeni 257 je brnkacka... protoze v ramci toho neustale to drzet na co nejmensim poctu bitu se to dela jako
(N*257)>>8
Takze ti staci hornich 8 bitu dat do spodnich a secist s puvodni hodnotou.
A ted si vem ze najit tohle pro kazde cislo je dost prace... a stejne nevis zda to nejde lepe... i kdyz to delas rucne.
dworkin@dw-A15:~/repositories/M4_FORTH$ ./check_word.sh 'PUSH(10) UDIV' ;[32:185] 10 u/ Variant HL/10 = (HL/2)*(65536/5)/65536 = (HL/2)*51*257/65536 ld B, H ; 1:4 10 u/ ld C, L ; 1:4 10 u/ srl B ; 2:8 10 u/ rr C ; 2:8 10 u/ 1x base xor A ; 1:4 10 u/ inc BC ; 1:6 10 u/ +19 rounding constant add HL, BC ; 1:11 10 u/ adc A, A ; 1:4 10 u/ 3x AHL add HL, HL ; 1:11 10 u/ inc HL ; 1:6 10 u/ +8 rounding constant adc A, A ; 1:4 10 u/ 6x AHL add HL, HL ; 1:11 10 u/ adc A, A ; 1:4 10 u/ 12x AHL add HL, HL ; 1:11 10 u/ adc A, A ; 1:4 10 u/ 24x AHL add HL, BC ; 1:11 10 u/ adc A, 0x00 ; 2:7 10 u/ 25x AHL add HL, HL ; 1:11 10 u/ adc A, A ; 1:4 10 u/ 50x AHL add HL, BC ; 1:11 10 u/ adc A, 0x00 ; 2:7 10 u/ 51x AHL with rounding constant 26..35 ld B, A ; 1:4 10 u/ (AHL * 257) >> 16 = (AHL0 + 0AHL) >> 16 = AH.L0 + A.HL = A0 + H.L + A.H ld C, H ; 1:4 10 u/ BC = "A.H" add HL, BC ; 1:11 10 u/ HL = "H.L" + "A.H" ld L, H ; 1:4 10 u/ adc A, 0x00 ; 2:7 10 u/ + carry ld H, A ; 1:4 10 u/ HL/10 = (HL/2)*(65536/5)/65536 = (HL/2)*(1+256)*51 >> 16 ; seconds: 0 ;[32:185]
Sorry, Z80 je trosku offtopic. .)