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.
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!
Besides the plain answer, there should be an explanation, so others can learn.old_cow_yellow said:You need to use reta, not ret.
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
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)old_cow_yellow said:You made an obvious typo. But there is no need to correct that.
**Attention** This is a public forum