⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdiv.asm

📁 Cordic algorithm description and C/Asm51 sourcecode examples
💻 ASM
字号:
;--------------------------------------------------------------;
; This function takes an unsigned 16.16 fixed point number     ;
; and divides it by another 16.16 fixed point number.          ;
;                                                              ;
; INPUT:    R0       Points to MSB of 32-bit divisor           ;
;           R0+4     Points to MSB of 32-bit dividend          ;
;                                                              ;      
; OUTPUT:   R0       Points to MSB of 32-bit quotient          ;
;                                                              ;
; NOTES: This function works fine but there is a lot of        ;
; room for improvement.  It uses a standard restoring-division ;
; algorithm. It consumes a lot of stack space and CPU cycles.  ;
; I'd like to have a try at a non-restoring division algorithm ;
; sometime which are reportedly a bit more efficient.          ;
;                                                              ;
; Basic idea from:                                             ;
;  http://www.ednmag.com/reg/1997/050897/10df_05.htm           ;
;--------------------------------------------------------------;
fdiv:
   push  0x000
   push  0x001
   push  0x002
   push  0x003
   push  0x006
   push  0x007
   push  psw
   push  b
            
   mov   r2,0x000          ; Get copy of R0 in R2
   
; Make room on stack for result
   mov   a,sp
   mov   r3,a
   inc   r3                ; Save ptr to result in R3
   add   a,#12
   mov   sp,a

; Make room on stack for 6-byte divisor.
   mov   a,sp
   mov   r4,a              ; Save ptr to 6-byte divisor in R4
   inc   r4
   add   a,#6
   mov   sp,a

; Check if division by 0
   mov   r0,0x002          ; Get pointer to divisor
   clr   a                 ; Clear logical accumulator
   mov   b,#4              ; Set count
FD1:
   orl   a,@r0             ; Add byte to logical sum
   inc   r0                ; Point to next byte
   djnz  b,FD1
   jnz   FD2               ; Not zero, then continue
   mov   b,#1              ; Else, exit with error
   ljmp  fdiv_exit         
FD2:

; Check if dividend=0
   mov   a,r2
   add   a,#4              ; Get pointer to dividend
   mov   r0,a
   clr   a                 ; Clear logical sum
   mov   b,#4              ; Get count
FD3:
   orl   a,@r0
   inc   r0
   djnz  b,FD3

; If dividend=0 then return 0
   jnz   FD5               ; Not zero, then continue
   mov   r0,0x002          ; Get pointer to return value.
   mov   b,#4              ; Get count
   clr   a                 ; Set to zero
FD4:           
   mov   @r0,a             ; Clear byte
   inc   r0                ; Point to next byte
   djnz  b,FD4
   ljmp  fdiv_exit         ; Exit, no error
FD5:
   
; Initialize 6 most significant bytes result=0
   mov   r0,0x003          ; Get point to result
   mov   b,#6              ; Get count
   mov   a,#0
FD6:
   mov   @r0,a             ; Clear byte
   inc   r0                ; Point to next byte
   djnz  b,FD6
      
; Load low 6 bytes result with dividend*(2^16)
   mov   a,r2
   add   a,#4              ; Get ptr to dividend in R0
   mov   r0,a
   mov   a,r3
   add   a,#6              ; Get ptr to low 6-bytes result in R1
   mov   r1,a
   mov   b,#4              ; Get count
FD7:
   mov   a,@r0             ; Fetch byte
   mov   @r1,a             ; Copy byte to result
   inc   r0                ; Increment the pointers
   inc   r1
   djnz  b,FD7
   clr   a
   mov   @r1,a             ; Clear low two 2-byte result
   inc   r1
   mov   @r1,a
   
; Initialize 6-byte divisor
   mov   r0,0x004          ; Get pointer to temp 6-byte divisor
   clr   a
   mov   @r0,a             
   inc   r0                ; Clear high two bytes
   mov   @r0,a             
   inc   r0                ; Get pointer to low 4-bytes in R0
   mov   r1,0x002          ; Get pointer to divisor in R1
   mov   b,#4
FD75:
   mov   a,@r1             ; Fetch byte
   mov   @r0,a             ; Put byte
   inc   r0                ; Increment ptrs
   inc   r1
   djnz  b,FD75            ; Loop
   
   mov   b,#48             ; Loop 48 times
FD8:
   
; Shift 96-bit result 1-bit left, LSB=0
   mov   a,r3           
   add   a,#11             ; Get pointer to LSB result in R0               
   mov   r0,a
   clr   c                 ; Clear for rotate
   mov   r6,#12            ; Get count in r6
FD9:
   mov   a,@r0             ; Fetch byte
   rlc   a                 ; Shift 1-bit left
   mov   @r0,a             ; Save back
   dec   r0                ; Point to next byte
   djnz  r6,FD9

; Subtract divisor from high 6 bytes result.
   mov   a,r3              ; Get pointer to LSB
   add   a,#5              ; of high 6 bytes result in R0
   mov   r0,a
   mov   a,r4
   add   a,#5              ; Get ptr to LSB divisor in R1
   mov   r1,a              
   clr   c                 ; Clear for subb
   mov   r6,#6
FD10:
   mov   a,@r0             ; Fetch byte from result
   subb  a,@r1             ; Subtract byte from divisor
   mov   @r0,a             ; Save back
   dec   r0                ; Decrement ptrs
   dec   r1
   djnz  r6,FD10           ; Loop

; Check result of subtraction
   jc    FD11              ; If result negative then jump

; LSB result=1
   mov   a,r3
   add   a,#11             ; Get ptr to LSB 96-bit result in R0
   mov   r0,a              
   mov   a,@r0             ; Fetch byte
   setb  acc.0             ; Set LSB
   mov   @r0,a             ; Save byte back
   
   sjmp  FD13              ; Continue
      
FD11:
   
; Add divisor back to high 4 bytes result.   
   mov   a,r3              ; Get pointer to LSB
   add   a,#5              ; of high 6 bytes result in R0
   mov   r0,a
   mov   a,r4
   add   a,#5              ; Get ptr to LSB divisor in R1
   mov   r1,a           
   clr   c                 ; Clear for subb
   mov   r6,#6
FD12:
   mov   a,@r0             ; Fetch byte from result
   addc  a,@r1             ; Subtract byte from divisor
   mov   @r0,a             ; Save back
   dec   r0                ; Decrement ptrs
   dec   r1
   djnz  r6,FD12        

FD13:
   djnz  b,FD8             ; Loop
   
; Return quotient
   mov   a,r3              
   add   a,#8              ; Get ptr to low 4-bytes result
   mov   r0,a
   mov   r1,0x002          ; Get pointer to return 
   mov   b,#4
FD14:
   mov   a,@r0             ; Fetch byte
   mov   @r1,a             ; Put byte
   inc   r0
   inc   r1
   djnz  b,FD14
      
   clr   b              ; Exit no error

fdiv_exit:

; Restore stack
   mov   a,sp
   clr   c
   subb  a,#18
   mov   sp,a

   mov   a,b         ; Get error code

   pop   b
   pop   psw
   pop   0x007
   pop   0x006
   pop   0x003
   pop   0x002
   pop   0x001
   pop   0x000
   ret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -