Please need a help with AN_1219 .

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Please need a help with AN_1219 .

Jump to solution
2,548 Views
ro_ok_bo
Contributor I

I need to use a 32/16bit unsigned Divide in assembler with the mc9s08aw32 or MC9S08GB60 .

Unfortunately I am a Beginner .

 

I have copied and editated the unsigned divide in this mode :

 

; export symbols
            XDEF Entry, main
            ; we use export 'Entry' as symbol. This allows us to
            ; reference 'Entry' either in the linker .prm file
            ; or from C/C++ later on

            XREF __SEG_END_SSTACK   ; symbol defined by the linker for the end of the stack

; include derivative specific macros
            INCLUDE 'mc9s08aw32.inc'

; variable/data section
MY_ZEROPAGE: SECTION  SHORT         ; Insert here your data definition


INTACC1 RMB 4 ;32-bit integer accumulator #1
INTACC2 RMB 4 ;32-bit integer accumulator #2
SPVAL   RMB 2 ;storage for stack pointer value


; code section
MyCode:     SECTION
main:    
        
Entry:   
                             

; Insert your code here

;*******Assegnazione Valori test.

          MOV      #$01,INTACC1
          MOV      #$F4,INTACC1+1           
          MOV      #$F4,INTACC1+2
         
          MOV      #$01,INTACC2
          MOV      #$F4,INTACC2+1         
         
;*******Assegnazione Valori test.

 

START     LDHX    #$450 ;load H:X with upper RAM boundary + 1
          TXS     ;move stack pointer to upper RAM boundary
          CLRH     ;clear H:X
         
          JSR     UDVD32 ;call 32 x 16 multiply routine

          BRA *   ;end of main routine

 

 

 

;********************************************************************************
;* 32 x 16 Unsigned Divide
;*
;* This routine takes the 32-bit dividend stored in INTACC1:INTACC1+3
;* and divides it by the 16-bit divisor stored in INTACC2:INTACC2+1.
;* The quotient replaces the dividend and the remainder replaces the divisor.
;*
UDVD32    EQU *

DIVIDEND  EQU INTACC1+2
DIVISOR   EQU INTACC2
QUOTIENT  EQU INTACC1
REMAINDER EQU INTACC1
;*
          PSHH        ;save h-reg value
          PSHA        ;save accumulator
          PSHX        ;save x-reg value
          AIS       #-3 ;reserve three bytes of temp storage
          LDA      #!32 ;
          STA      3,SP ;loop counter for number of shifts
          LDA      DIVISOR ;get divisor MSB
          STA      1,SP ;put divisor MSB in working storage
          LDA      DIVISOR+1 ;get divisor LSB
          STA      2,SP ;put divisor LSB in working storage
;*
;* Shift all four bytes of dividend 16 bits to the right and clear
;* both bytes of the temporary remainder location
;*
          MOV      DIVIDEND+1,DIVIDEND+3 ;shift dividend LSB
          MOV      DIVIDEND,DIVIDEND+2 ;shift 2nd byte of dividend
          MOV      DIVIDEND-1,DIVIDEND+1 ;shift 3rd byte of dividend
          MOV      DIVIDEND-2,DIVIDEND ;shift dividend MSB
          CLR      REMAINDER ;zero remainder MSB
          CLR      REMAINDER+1 ;zero remainder LSB
;*
;* Shift each byte of dividend and remainder one bit to the left
;*
SHFTLP    LDA      REMAINDER ;get remainder MSB
          ROLA                ;shift remainder MSB into carry
          ROL      DIVIDEND+3 ;shift dividend LSB
          ROL      DIVIDEND+2 ;shift 2nd byte of dividend
          ROL      DIVIDEND+1      ;shift 3rd byte of dividend
          ROL      DIVIDEND      ;shift dividend MSB
          ROL      REMAINDER+1 ;shift remainder LSB
          ROL      REMAINDER ;shift remainder MSB
;*
;* Subtract both bytes of the divisor from the remainder
;*
          LDA      REMAINDER+1      ;get remainder LSB
          SUB      2,SP ;          subtract divisor LSB from remainder LSB
          STA      REMAINDER+1 ;     store new remainder LSB
          LDA      REMAINDER ;     get remainder MSB
          SBC      1,SP ;subtract divisor MSB from remainder MSB
          STA      REMAINDER ;store new remainder MSB
          LDA      DIVIDEND+3 ;get low byte of dividend/quotient
          SBC      #0 ;dividend low bit holds subtract carry
          STA      DIVIDEND+3 ;store low byte of dividend/quotient
;*
;* Check dividend/quotient LSB. If clear, set LSB of quotient to indicate
;* successful subraction, else add both bytes of divisor back to remainder
;*
          BRCLR      0,DIVIDEND+3,SETLSB ;check for a carry from subtraction
                                    ;and add divisor to remainder if set
          LDA      REMAINDER+1 ;get remainder LSB
          ADD      2,SP ;add divisor LSB to remainder LSB
          STA      REMAINDER+1 ;store remainder LSB
          LDA      REMAINDER ;get remainder MSB
          ADC      1,SP ;add divisor MSB to remainder MSB
          STA      REMAINDER ;store remainder MSB
          LDA      DIVIDEND+3 ;get low byte of dividend
          ADC      #0 ;add carry to low bit of dividend
          STA      DIVIDEND+3 ;store low byte of dividend
          BRA      DECRMT ;do next shift and subtract
SETLSB    BSET      0,DIVIDEND+3 ;set LSB of quotient to indicate successive subtraction
DECRMT    DBNZ      3,SP,SHFTLP ;decrement loop counter and do next shift
;*
;* Move 32-bit dividend into INTACC1:INTACC1+3 and put 16-bit
;* remainder in INTACC2:INTACC2+1
;*
          LDA      REMAINDER ;get remainder MSB
          STA      1,SP ;temporarily store remainder MSB
          LDA      REMAINDER+1 ;get remainder LSB
          STA      2,SP ;temporarily store remainder LSB
          MOV      DIVIDEND,QUOTIENT ;
          MOV      DIVIDEND+1,QUOTIENT+1 ;shift all four bytes of quotient
          MOV      DIVIDEND+2,QUOTIENT+2 ; 16 bits to the left
          MOV      DIVIDEND+3,QUOTIENT+3 ;
          LDA      1,SP ;get final remainder MSB
          STA      INTACC2 ;store final remainder MSB
          LDA      2,SP ;get final remainder LSB
          STA      INTACC2+1 ;store final remainder LSB
;*
;* Deallocate local storage, restore register values, and return from
;* subroutine
;*
          AIS      #3      ;deallocate temporary storage
          PULX           ;restore x-reg value
          PULA           ;restore accumulator value
          PULH           ;restore h-reg value           
          RTS 
           
;******FINE_SUB************************************

 

I use CW_6.0 and when i try to use MAKE  ;  it show mi this message of warning :

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 94  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 94  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 95  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 95  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 96  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 96  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 97  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 97  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 98  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 99  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 105  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 106  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 107  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 108  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 109  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 110  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 127  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 139  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 149  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 149  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 150  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 150  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 151  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 151  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 152  

Warning : A13003: Value is truncated to one byte

Conversione_Gradi_HEX_OK.asm line 152  

 

Who can help mi to understand  the correct way for make the unsigned Divide  .......PLEASE ?

where' s the trouble?

 

Sorry for my bad English. 

Labels (1)
0 Kudos
Reply
1 Solution
760 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

Does the subroutine perform correctly, in spite of the warnings? I suspect that it may do so.

 

The instructions to which the warnings apply can utilize zero page variables only. However, the labels that are used within the instructions are actually defined within some equates. So presumably the assembler is not explicitly aware of their validity, and assumes 8-bit addressing mode, thus resulting in the warnings.

 

The warnings appear to be eliminated by using the variables INTACC1 and INTACC2 directly, rather than the equates DIVIDEND, REMAINDER, etc.

 

Another possibility is to define the variables and equates in a separate file, containing XDEFs for both the variables and the equates. Then, within the main file, by using XREFB for the variables and equates, the addressing mode is explicitly defined, and the warnings should be eliminated.

 

The code within the application note was originally written for a different assembler than CW, probably as an absolute assembly project. Presumably these warnings were not generated by the ooriginal assembler.

 

Another important point - you do not appear to have initialised the stack pointer at the start of your main code. 

 

Regards,

Mac

 

Message Edited by bigmac on 2009-09-16 07:51 AM

View solution in original post

0 Kudos
Reply
6 Replies
760 Views
ro_ok_bo
Contributor I

It's a BEAUTIFUL DAY.

 

Now with " LDA     #32"   work.

 

Many many THANK's to everybody for the help. 

Have a nice day to everibady.

0 Kudos
Reply
760 Views
ro_ok_bo
Contributor I

Hallo bigmac  and many thank's for the anwer :

I have tried to reedited my asm_file with initalizzated the RAM at (Z_RAMStart).

 

This is the file.asm :


            INCLUDE 'MC9S08AW32.inc'

            XDEF _Startup
            ABSENTRY _Startup


            ORG    Z_RAMStart ;ORG    RAMStart         ; Insert your data definition here

INTACC1 RMB 4   ;32-bit integer accumulator #1
INTACC2 RMB 4   ;32-bit integer accumulator #2
SPVAL   RMB 2   ;storage for stack pointer value


            ORG    ROMStart

_Startup:
            LDHX   #RAMEnd+1        ; initialize the stack pointer
            TXS
            CLI                     ; enable interrupts

mainLoop:

START   LDHX  #$100 ;load H:X with upper RAM boundary + 1
        TXS         ;move stack pointer to upper RAM boundary
        CLRH        ;clear H:X

     
;*******Assegnazione Valori test.

          MOV      #$00,INTACC1
          MOV      #$F4,INTACC1+1           
          MOV      #$00,INTACC1+2
          MOV      #$00,INTACC1+3         
          MOV      #$01,INTACC2
          MOV      #$A0,INTACC2+1         
;***********************************       

          JSR     UDVD32              
          nop
          nop
          nop
          STOP     ; END..........
                                                            
         
;* SUB:UDVD32 ______ 32 x 16 Unsigned Divide
;* This routine takes the 32-bit dividend stored in INTACC1:INTACC1+3
;* and divides it by the 16-bit divisor stored in INTACC2:INTACC2+1.
;* The quotient replaces the dividend and the remainder replaces the divisor.

UDVD32    EQU *

DIVIDEND  EQU INTACC1+2
DIVISOR   EQU INTACC2
QUOTIENT  EQU INTACC1
REMAINDER EQU INTACC1

          PSHH                     ;save h-reg value
          PSHA                     ;save accumulator
          PSHX                     ;save x-reg value
          AIS      #-3             ;reserve three bytes of temp storage
          LDA      #!32            ;
          STA      3,SP           ;loop counter for number of shifts
          LDA      DIVISOR       ;get divisor MSB
          STA      1,SP            ;put divisor MSB in working storage
          LDA      DIVISOR+1    ;get divisor LSB
          STA      2,SP            ;put divisor LSB in working storage

;* Shift all four bytes of INTACC11 16 bits to the right and clear
;* both bytes of the temporary remainder location

          MOV      DIVIDEND+1,DIVIDEND+3 ;shift dividend LSB
          MOV      DIVIDEND,DIVIDEND+2    ;shift 2nd byte of dividend
          MOV      DIVIDEND-1,DIVIDEND+1 ;shift 3rd byte of dividend
          MOV      DIVIDEND-2,DIVIDEND    ;shift dividend MSBshift 3rd byte of dividend
          MOV      DIVIDEND-2,DIVIDEND    ;shift dividend MSB
          CLR      REMAINDER                   ;zero remainder MSB
          CLR      REMAINDER+1               ;zero remainder LSB

;* Shift each byte of dividend and remainder one bit to the left

SHFTLP    LDA      REMAINDER ;get remainder MSB
          ROLA                        ;shift remainder MSB into carry
          ROL      DIVIDEND+3    ;shift dividend LSB
          ROL      DIVIDEND+2    ;shift 2nd byte of dividend
          ROL      DIVIDEND+1    ;shift 3rd byte of dividend
          ROL      DIVIDEND       ;shift dividend MSB
          ROL      REMAINDER+1 ;shift remainder LSB
          ROL      REMAINDER    ;shift remainder MSB

;* Subtract both bytes of the divisor from the remainder

          LDA      REMAINDER+1      ;get remainder LSB
          SUB      2,SP                  ;          subtract divisor LSB from remainder LSB
          STA      REMAINDER+1     ;     store new remainder LSB
          LDA      REMAINDER         ;     get remainder MSB
          SBC      1,SP                 ;subtract divisor MSB from remainder MSB
          STA      REMAINDER        ;store new remainder MSB
          LDA      DIVIDEND+3       ;get low byte of dividend/quotient
          SBC      #0                   ;dividend low bit holds subtract carry
          STA      DIVIDEND+3      ;store low byte of dividend/quotient

;* Check dividend/quotient LSB. If clear, set LSB of quotient to indicate
;* successful subraction, else add both bytes of divisor back to remainder

          BRCLR    0,DIVIDEND+3,SETLSB ;check for a carry from subtraction
                                                    ;and add divisor to remainder if set
          LDA      REMAINDER+1        ;get remainder LSB
          ADD      2,SP                   ;add divisor LSB to remainder LSB
          STA      REMAINDER+1       ;store remainder LSB
          LDA      REMAINDER          ;get remainder MSB
          ADC      1,SP                  ;add divisor MSB to remainder MSB
          STA      REMAINDER         ;store remainder MSB
          LDA      DIVIDEND+3         ;get low byte of dividend
          ADC      #0                    ;add carry to low bit of dividend
          STA      DIVIDEND+3       ;store low byte of dividend
          BRA      DECRMT            ;do next shift and subtract
         
SETLSB    BSET     0,DIVIDEND+3   ;set LSB of quotient to indicate successive subtraction
DECRMT    DBNZ     3,SP,SHFTLP   ;decrement loop counter and do next shift

;* Move 32-bit dividend into INTACC1:INTACC1+3 and put 16-bit
;* remainder in INTACC2:INTACC2+1

          LDA      REMAINDER      ;get remainder MSB
          STA      1,SP              ;temporarily store remainder MSB
          LDA      REMAINDER+1  ;get remainder LSB
          STA      2,SP             ;temporarily store remainder LSB
          MOV      DIVIDEND,QUOTIENT ;
          MOV      DIVIDEND+1,QUOTIENT+1    ;shift all four bytes of quotient
          MOV      DIVIDEND+2,QUOTIENT+2    ; 16 bits to the left
          MOV      DIVIDEND+3,QUOTIENT+3    ;
          LDA      1,SP           ;     get final remainder MSB
          STA      INTACC2     ;store final remainder MSB
          LDA      2,SP           ;get final remainder LSB
          STA      INTACC2+1  ;store final remainder LSB

;* Deallocate local storage, restore register values, and return from
;* subroutine

          AIS      #3    ;deallocate temporary storage
          PULX           ;restore x-reg value
          PULA           ;restore accumulator value
          PULH           ;restore h-reg value
          RTS            ;return       


;**************************************************************
;* spurious - Spurious Interrupt Service Routine.             *
;*             (unwanted interrupt)                           *
;**************************************************************
spurious:                           ; placed here so that security value
            NOP                     ; does not change all the time.
            RTI
;**************************************************************
;*                 Interrupt Vectors                          *
;**************************************************************
            ORG   $FFFA
            DC.W  spurious          ;
            DC.W  spurious          ; SWI
            DC.W  _Startup          ; Reset

Now It start and run in debug with IDE_WORK.

Now there is another problem ;  I find a wrong result at the end of the Subrutine.

If you take a look to the value of the variable :


          MOV      #$00,INTACC1
          MOV      #$F4,INTACC1+1           
          MOV      #$00,INTACC1+2
          MOV      #$00,INTACC1+3         
          MOV      #$01,INTACC2
          MOV      #$A0,INTACC2+1         
 the result must be >>>>> 96.27h ; bat unfortunately isn't so .

 

Where is the miss match ???

 

Many THANK'S again for the help.

0 Kudos
Reply
760 Views
bigmac
Specialist III

Hello,

 

It seems that the problem is with the following code.

 

        AIS  #-3    ; reserve three bytes of temp storage
        LDA  #!32

        STA  3,SP   ; loop counter for number of shifts

 

The CW assembler seems to have problems with the highlighted line, but did not generate an error message.  It interprets the line as lda #0x00, which is obviously not correct.  When the line was altered to LDA #32, the expected result was obtained from the sub-routine.

 

The lack of some sort of error message did surprise me.

 

Regards,

Mac

0 Kudos
Reply
760 Views
pgo
Senior Contributor V

Dear Bigmac,

 

The Codewarrior assembler accepts C expressions so interprets !32 as 'not' 32.  32 being 'true' this gives 'false' i.e. 0.

 

Certainly a bit confusing but legal.

 

bye

 

0 Kudos
Reply
760 Views
bigmac
Specialist III

Hello pgo,

 

The main problem here is that the code in question appears in a Freescale Application Note (admittedly originating in the Motorola days), which is therefore not now entirely compatible with the CW assembler.  I wonder how many other AN's also have problems with the published assembly code?

 

For the earlier assemblers, the prefix '!' was used to explicitly indicate a decimal number (since some assemblers defaulted to hexadecimal).  Unfortunately, this does give incompatibility with "C expression" notation.

 

In the process of converting old assembly files over to CW, the incompatibilities will generally produce errors or warnings.  This is the first instance I have come across where there was no warning of a potential problem, for whatever reason.

 

Regards,

Mac

 

0 Kudos
Reply
761 Views
bigmac
Specialist III

Hello, and welcome to the forum.

 

Does the subroutine perform correctly, in spite of the warnings? I suspect that it may do so.

 

The instructions to which the warnings apply can utilize zero page variables only. However, the labels that are used within the instructions are actually defined within some equates. So presumably the assembler is not explicitly aware of their validity, and assumes 8-bit addressing mode, thus resulting in the warnings.

 

The warnings appear to be eliminated by using the variables INTACC1 and INTACC2 directly, rather than the equates DIVIDEND, REMAINDER, etc.

 

Another possibility is to define the variables and equates in a separate file, containing XDEFs for both the variables and the equates. Then, within the main file, by using XREFB for the variables and equates, the addressing mode is explicitly defined, and the warnings should be eliminated.

 

The code within the application note was originally written for a different assembler than CW, probably as an absolute assembly project. Presumably these warnings were not generated by the ooriginal assembler.

 

Another important point - you do not appear to have initialised the stack pointer at the start of your main code. 

 

Regards,

Mac

 

Message Edited by bigmac on 2009-09-16 07:51 AM
0 Kudos
Reply