logo.jpg                 movie1.gif            so20_1s.gif

Esempi C - ASM

 

In questa pagina vi sono alcuni esempi in assembly di routine matematiche di
pubblico dominio.

 

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  

 

movled2.gif (2014 byte)  
                                                                                
;+-----------------------------------------------------------------------+
;|                      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      

 

movled2.gif (2014 byte)

 

;|===========================================================================|
;|                               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      

 

movled2.gif (2014 byte)

 

;|===========================================================================|
;|                               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       

 

Pagina non ancora ultimata

lavori_in_corso.gif (6366 byte)

 

 

Precedente Home Successiva

super.gif

Per informazioni Inviare un messaggio di e-mail a: calatroc@libero.it