This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Stack pointer - Assembly function called within C function (CCS)

Hello!

Can someone help me with the following problem:

I use the "Binary to BCD Conversion" from the application reports 5.5.3. (with CCS).
It is an assembly function and it is called within a C function.
Parameters are passed to- and returned from the assembly function.
However, after running through the assembly function, the stack pointer does not point
to the adress as before, when entering the assembly function. In other words:

SP:
0x0030DC  327A    //SP in assembly function (correct)
0x0030DE  0000    //SP after running through assembly function (not correct)(should be at 0x0030E0)
0x0030E0   3128    //SP before entering assemby function (correct)
0x0030E2   0000



Assembly function:


            .def    UintToBCD              ; Export symbol outside this file
            .text                                      ; Assemble into program memory
UintToBCD:                                    ; Name of function as usual
            mov.w    R12,R14             ; Move input and leave R12 free for result
            clr.w    R12                         ; Clear registers for result
            clr.w    R13
            mov.w    #0x0010,R15     ; Initialize loop counter to number of bits
LoopStart:
            rla.w    R14                        ; Shift msb of input into carry bit
            dadd.w    R12,R12           ; R13:R12 = 2*R13:R12 + carry bit DECIMALLY!
            dadd.w    R13,R13           ;     lsword then msword
            dec.w    R15                      ; Decrement loop counter
            jnz    LoopStart                  ; Repeat if nonzero
            ret                
            .end

Thanks a lot!

  • You need to use reta, not ret.

  • old_cow_yellow said:
    You need to use reta, not ret.

    Besides the plain answer, there should be an explanation, so others can learn.

    On MSPs with the MSP430X core, there coexist two sets of instrucitons. One is the classic 16 bit addressing, the other one uses 20 bit addressing.
    When using a C compiler, the code memory model (small/large) determines whether function pointers are 16 or 20 bit. In the second case, code can reside above 64k. To make this work, the CALLA instruction is used instead of the traditional CALL, and puts a 20 (32) bit return address on the stack. For C code and libraries, the linker will get the information about the used code model in the object file and will complain if incompatible models are used.
    In Assembly code, however, the coder has picked the instructions and is responsible for picking the right ones. In this case, a 20(32) bit RETA needs to be used rather than the traditional 16 bit RET instruction. Else the CPU will put 4 bytes on stack on function call but read only 2 bytes. This will work at first if the calling function is in lower 64k, but then there is a superfluous 0x0000 word on the stack which will make problems when this calling function returns - or sooner.

    BTW: for ISRs, there's still the RETI instruction to be used. On an interrupt, the additional 4 address bits are stored together with the status register, so no additional word is required.

  • JMG,

    Thanks for the explanation. I was lazy.

    You made an obvious typo. But there is no need to correct that. Readers who deserve you labor will detect that typo and still benefit from it. Others who only want you to "give me sample code immediately" will get what they deserve.

    -- OCY

  • old_cow_yellow said:
    You made an obvious typo. But there is no need to correct that.

    You're of course right. (about the typo and the rest). However, I decided to correct it, as was in explanatory text and not in psedo-code or real code. (in which case I'd agree that understanding the code would lead to detecting the typo)

  • JMG,

    Thank you for the explicit explanation!

**Attention** This is a public forum