|
|
|
In questa pagina vi sono alcuni esempi in assembly di routine matematiche di
ROUTINE PER ST6: .DISPLAY " DIVISION "
.EJECT ; generate a new page in the output listing.
;+--------------------------------------------------------------------------+
;| DIVISION A / B |
;| |
;| WRITTEN BY : Jean-Francois GATTO |
;| DATE : 16/09/91 |
;| REVISION : V01.00 |
;| |
;| SOFTWARE DESCRIPTION : This routine divides two 8 bit numbers, A and |
;| B, the result is saved into an 8 bit register. |
;| A and B >= 0. |
;| |
;| INPUT PARAMETERS : NUMBER_A register contains the number A. |
;| NUMBER_B register contains the number B. |
;| |
;| INTERNAL PARAMETERS : SAVE_A register saves the accumulator. |
;| COUNTER register contains the shift counter. |
;| |
;| OUTPUT PARAMETERS : RESULT register contains the result. |
;| REMAIND register contains the remainder. |
;| |
;| WORST CASE SPEED : 410 cycles |
;| WORST EXECUTION TIME : Tcyc x 410 = 666 us at 8 Mhz |
;| BYTE : 52 bytes |
;| |
;| EXAMPLE : ;***** program ***** |
;| .ORG 880h |
;| LDI NUMBER_A,E7h |
;| LDI NUMBER_B,10h |
;| CALL DIVISION |
;| - do... |
;| - do... |
;| .END |
;| ;***** subroutine ***** |
;| .INPUT " DIVIS.ASM " |
;| |
;+--------------------------------------------------------------------------+
DIVISION
; Initialize registers and save the contexte.
LD SAVE_A,A ; save the accumulator.
CLR RESULT ; clear the result register.
CLR REMAIND ; clear the remainder register.
; Test A and B in order to enable the division subroutine.
LD A,NUMBER_B ; B = 0 then the result = 0 ( not valid ).
JRNZ DIV0
END_DIV LD A,SAVE_A ; restore the accumulator.
RET
DIV0 LD A,NUMBER_A ; A = 0 then the result = 0.
JRZ END_DIV
; Division subroutine.
ADDI A,0FFh ; clear the carry.
LDI COUNTER,08h ; load the shift counter.
LD A,NUMBER_A ; \
RLC A ; | rotate left and save in result register.
LD RESULT,A ; /
DIV1 LD A,REMAIND ; \
RLC A ; | rotate left the remainder register in
LD REMAIND,A ; / order to include the carry.
SUB A,NUMBER_B
JRC DIV2 ; test if the subtraction is valid.
LD REMAIND,A
DIV2 LD A,RESULT ; \
RLC A ; | rotate left the result register.
LD RESULT,A ; /
DEC COUNTER
JRZ DIV3
JP DIV1
DIV3 COM A ; complement the result.
LD RESULT,A
JP END_DIV
;+-----------------------------------------------------------------------+ ;| SGS THOMSON Microelectronics | ;| | ;| ST6 Software Library: DIV_24.ASM | ;| --------------------- ---------- Revision: 0.01 | ;| Date: 2nd Sept 93 | ;| Author: David Lamb | ;| | ;| Description | ;| ----------- | ;| 24 bit by pseudo-24 bit divide routine, developed as a benchmark | ;| routine only. | ;| | ;| This routine assumes that the denominator is held in D1/D2/D3 and | ;| the numerator is held in PN1/PN2/PN3. The result appears in registers | ;| N3/N4/N5/N6. | ;| | ;| The routine is actually a 24/16 bit divide. If the most significant | ;| byte of the 24 bit denominator is non-zero, the two upper bytes are | ;| used. If the most significant byte is zero, the two lower bytes are | ;| used. | ;| | ;| Worst Case Timings (including setup and return) | ;| ----------------------------------------------- | ;| 33 loop (MS byte of denominator non-zero) divide: 1225 instr. cycles | ;| 41 loop (MS byte of denominator = zero) divide: 1489 instr. cycles | ;| | ;| At 8MHz oscillator frequency, 1 instruction cycle is 1.625us. | ;| therefore 33 loop divide = 1.99 ms (approx) | ;| 41 loop divide = 2.42 ms (approx) | ;| | ;| Principle of Operation | ;| ---------------------- | ;| The numerator is shifted, bit by bit, past the denominator. At each | ;| step, the denominator is subtracted from the numerator (16 bit sub). | ;| If the numerator is smaller than the denominator, the carry flag is | ;| set, and is shifted into the lsb of the extended numerator. | ;| If the numerator is larger than, or equal to, the denominator, the | ;| carry flag is reset, and is shifted into the lsb of the extended | ;| numerator. Additionally, the most significant 16 bits of the extended | ;| numerator are replaced with the result of the subtraction. | ;| Finally, the 4 byte result (N3..N6) is complemented, as the sense of | ;| the carry flag is opposite to the required result. | ;| | ;| Shift numerator LEFT across denominator | ;| <------ <------ <------ <------ <------ <--- | ;| +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ | ;| | N1 | | N2 | | N3 | | N4 | | N5 | | N6 | [CY] | ;| +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ | ;| PN1 PN2 PN3 | ;| | | \___________________________/ | ;| | | original 24 bit numerator | ;| | | | ;| +-----+ +-----+ | ;| | D1 | | D2 | --> 16 bit denominator | ;| +-----+ +-----+ | ;| | ;| Subtraction | ;| | ;| NOTE: THIS ROUTINE HAS NOT BEEN FULLY TESTED | ;+-----------------------------------------------------------------------+ .DISPLAY "" .DISPLAY " DIV_24 " .DISPLAY " ------ " .DISPLAY "" ;+-----------------------------------------------------------------------+ ;+-----------------------------------------------------------------------+ ;+-------------------------------+ ;| assembler / linker directives | ;+-------------------------------+ .PP_ON ;enable linker .W_ON ;enable data ROM windowing .DP_ON ;enable data space paging ;+------------------------+ ;| data space definitions | ;+------------------------+ ; general purpose definitions A .DEF 0FFH,0FFH,0FFH,M ;accumulator X .DEF 080H,0FFH,0FFH ;index register Y .DEF 081H,0FFH,0FFH ;index register V .DEF 082H,0FFH,0FFH ;short access register W .DEF 083H,0FFH,0FFH ;short access register ;numerator definitions N1 .DEF 084H,0FFH,0FFH,M ;numerator working registers N2 .DEF 085H,0FFH,0FFH,M N3 .DEF 086H,0FFH,0FFH,M N4 .DEF 087H,0FFH,0FFH,M N5 .DEF 088H,0FFH,0FFH,M N6 .DEF 089H,0FFH,0FFH,M ;denominator definitions D1 .DEF 08AH,0FFH,0FFH ;denominator registers D2 .DEF 08BH,0FFH,0FFH D3 .DEF 08CH,0FFH,0FFH ;operation counter COUNTER .DEF 08DH,0FFH,0FFH ;loop counter for divide cycle ;temporary storage TEMP .DEF 08EH,0FFH,0FFH ;general purpose storage ;parameter passing PN1 .DEF 090H,0FFH,0FFH,M ;numerator registers PN2 .DEF 091H,0FFH,0FFH,M PN3 .DEF 092H,0FFH,0FFH,M ;management DIV_FLGS .DEF 093H,0FFH,0FFH ;program control flags BORROW .EQU 00H ;+------------+ ;| CODE SPACE | ;+------------+ .SECTION 1 RESTART: ; Initialize registers LD A,PN3 ;transfer numerator into working regs. LD N5,A LD A,PN2 LD N4,A LD A,PN1 LD N3,A CLR N1 ;intialize remaining numerator regs. CLR N2 CLR N6 LDI COUNTER,#33 ;operations count for ;24 bit denominator ;initialise carry ADDI A,#0FFH ;alternative way of setting carry ;copy denominator into working regs. LD A,D2 ;initialize denominator working regs. LD W,A LD A,D1 LD V,A ; check denominator MS byte for non-zero LD A,V JRNZ DIV_LOOP ; if MS byte is zero, use lower bytes LD A,W LD V,A LD A,D3 LD W,A LDI COUNTER,#41 ;operations count for ;16 bit denominator DIV_LOOP: ;ripple through numerator LD A,N6 RLC A LD N6,A LD A,N5 RLC A LD N5,A LD A,N4 RLC A LD N4,A LD A,N3 RLC A LD N3,A LD A,N2 RLC A LD N2,A LD A,N1 RLC A LD N1,A ; Now subtract denominator from most significant 16 bits of extended ; numerator. SUB_16: RES BORROW,DIV_FLGS ;clear borrow flag LD A,N2 ;get lower byte SUB A,W ;subtract denominator LD TEMP,A ;keep copy of result LD A,N1 ;get upper byte JRNC SUB_MSB ;jump if prev. subtract OK SET BORROW,DIV_FLGS ;indicate borrow SUB_MSB: SUB A,V ;subtract denominator JRC END_SUB ;jump if denom. > numer. JRR BORROW,DIV_FLGS,SM_100 ;jump if no borrow SUBI A,#01h ;account for borrow JRC END_SUB ;jump if denom > numer. SM_100: LD N1,A ;update numerator LD A,TEMP LD N2,A END_SUB: DEC COUNTER ;decrement loop counter JRZ DONE ;done? JP DIV_LOOP ;no, next loop DONE: ;complement result LD A,N6 COM A LD N6,A LD A,N5 COM A LD N5,A LD A,N4 COM A LD N4,A LD A,N3 COM A LD N3,A END_D24: STOP ;replace with RET if used as subroutine ;+-----------------------------------------------------------------------+ ;+-----------------------------------------------------------------------+ ;+---------+ ;| VECTORS | ;+---------+ .SECTION 32 ;vector space .BLOCK 0Eh ;reserve space for interrupt vectors JP RESTART ;reset vector .END
;|===========================================================================| ;| MULTIPLICATION | ;| This routine multiplies the bytes A and B. The result is saved into 2 | ;| bytes of ram space. | ;|===========================================================================| mul clr res_msb ; Clear the most significant byte of the result. clr res_lsb ; Clear the least significant byte of the result. ld a,number_b ; If B = 0 the result = 0. jrnz mul1 end_mul ret mul1 ld a,number_a ; If A = 0 the result = 0. jrz end_mul ld a,number_b add a,res_lsb ; Number_b + res_lsb. ld res_lsb,a ; Store the result in the least significant byte. jrnc mul2 inc res_msb ; Increase the most significant byte. mul2 dec number_a jp mul1
;|===========================================================================|
;| MULTIPLICATION |
;| This routine multiplies the numbers A and B in floating point arithmetic. |
;| Each number A and B are stored into 5 bytes of ram space. The result is |
;| saved into 16 bytes of ram space. In this routine, the point position of |
;| the resultant multiplication is fixed. |
;|===========================================================================|
multicn ldi a,pointr0
sub a,pointa
sub a,pointb
inc a
ld addr_r,a ; Save the lsb address of the resultant
; multiplcation.
ldi addr_a,lsb_a ; Save the lsb address of the number A.
ldi y,lsb_a ; Load the lsb address of the number A.
ldi byte_num,05h ; Load the byte number has to be multiplied.
multic1 ld a,(y)
jrnz multic2 ; Test if the byte of the number A = 0 ?
jp multic8
multic2 ldi x,lsb_b ; Load the lsb address of the number B.
ld a,addr_r
ld y,a ; Load the address of the resultant
; multiplication byte.
multic3 ld a,(x)
add a,(y) ; Byte B + resultant multiplication byte .
ld (y),a ; Store into resultant multiplication byte.
subi a,0ah ; Test if the result < 10.
jrc multic4
ld (y),a
multic4 inc y ; Next resultant multiplication byte.
jrc multic5
inc (y) ; Store the carry into the next resultant
; multiplication byte.
multic5 ld a,y
cpi a,msb_r
jrc multic6
jp erreur
multic6 ld a,x
cpi a,msb_b ; Test if all bytes of the number B are added ?
jrnc multic7
inc x ; Next number B byte.
jp multic3
multic7 ld a,addr_a
ld y,a
dec (y) ; Decremente the number A byte.
jp multic1
multic8 inc addr_a ; Next number A byte.
ld a,addr_a
ld y,a
inc addr_r ; Shift left the lsb of the resultant
; multiplication.
dec byte_num
jrz multic9 ; Test for the end of multiplication ?
jp multic1
multic9 set mult_val,ope_flag
jp end_mult
erreur res mult_val,ope_flag
end_mult ret
|
|
Per informazioni Inviare un messaggio di e-mail a: calatroc@libero.it |