Divisions en assembleur Z80 Le Z80 est un processeur 8 bits, il n'est pas capable de réaliser nativement des divisions ou des multiplications. Voici une petite compilation de routines de division (wikiti, Z80 heaven, grauw, cpcwiki)
division 8 x 8 non signée => C
c_divise_par_d ; résultat dans le registre C ld b,8 xor a .loop sla c rla cp d jr c,.skip inc c sub d djnz .loop retdivision 16 x 8 non signée => C hl_divise_par_c ; résultat dans HL, et le reste dans A ld b,16 xor a .loop add hl,hl rla cp c jr c,.skip inc l sub c .skip djnz .loop retdivision 16 x 16 non signée => A:C bc_divise_par_de ; résultat dans A:C, et le reste dans HL ld hl,0 ld a,b ld b,16 .loop sll c rla adc hl,hl sbc hl,de jr nc,$+4 add hl,de dec c djnz .loop retdivision 32 x 32 non signée BC':BC / DE':DE => IY:IX + remainder BC':BC Suite au cours sur les divisions, voici la routine optimisée avec la méthode naïve. Si on compare avec des méthodes classiques, elle est beaucoup plus rapide (genre, beaucoup, presque 10 fois plus rapide) quand le résultat est petit et 50% plus lent quand le résultat est trèèèès grand. Selon vos cas d'usage et les besoins en mantisse, utilisez l'une ou l'autre. J'ai comparé avec celle de [ Zeda ], seuleque j'ai finalement trouvée (Merci Prodatron!) permettant de diviser deux nombres 32 bits. Par ailleurs, le code n'utilise pas de mémoire vive et repose uniquement sur les registres. ; Z80 division 32 bits unsigned div32unsigned ; input : ; dividende in BC':BC ; divisor in DE':DE ; output : ; result in IY :IX ; remainder in BC':BC ; ; this function is suitable for ROM usage (no memory is used) ; this function can be enhanced to not use STACK (remove the RET and add a JR at the end) ; known limitation => divisor on 31 bits maximum ; speed depends on result size ; (expect from 100 nops for a small quotient to 2000 nops for a big quotient); find max iterations to do and prepare divisor xor a jr .firstIterationQbit .findMaxQbit sla de : exx : rl de : exx ; divisor x 2 .firstIterationQbit inc a : ld hl,bc : or a : sbc hl,de : exx : ld hl,bc : sbc hl,de : exx : jp nc,.findMaxQbit ; compare dividende to divisor .maxQ cp 1 : jr z,.noadjust : exx : srl de : exx : rr de : dec a : .noAdjust ; initialise quotient ld ix,0 ld iy,0 ; iterate using binary jr .firstIteration ; compute quotient with almost ALL registers available .computeQuotientBit add iy,iy : add ix,ix : jr nc,.NextIteration : inc yl ; shift quotient .firstIteration or a ; reset Carry for next SBC .NextIteration ld hl,bc : sbc hl,de : exx : ld hl,bc : sbc hl,de : jp c,.bit0 ; cannot substract => 0 .bit1 ; update remainder + shift divisor ld bc,hl : srl de : exx : rr de : ld bc,hl inc xl ; inject bit to quotient dec a : jr nz,.computeQuotientBit ret .bit0 ; do not touch remainder, shift and loop srl de : exx : rr de ; shift divisor dec a : jr nz,.computeQuotientBit ret Vous pouvez jeter un oeil dans les liens pour trouver encore plus de routines différentes, en particulier sur les sites de calculatrices Texas Instrument. CPCrulez[Content Management System] v8.732-desktop/c Page créée en 140 millisecondes et consultée 8 foisL'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko. |
|