Search code examples
assemblyavr

Returning More Than 1 Byte to a Function in Assembly


I'm new to assembly (I'm using an Arduino Uno with AVR assembly) and I can't figure out how to return variables of more than 1 byte from an assembly function. So far, I have only needed to return bytes, and I have simply modified the r24 register with mov and ldi to the value I wanted to return. When I call ret, the function returns the value in register r24 to a program in C. But how do I return values larger than 8 bytes? Basically, how do I use memory instead of the registers.


Solution

  • On the page you have linked in your comment (gcc.gnu.org/wiki/avr-gcc) read the chapter "Calling Convention". Unfortunately it's a bit more complicated than for other CPUs.

    If the value returned is longer than 8 bytes the C compiler will allocate the memory and pass the address of the memory in registers R25:R24.

    All arguments are shifted "down" by two registers. Example:

    byte someFunction1(byte a, byte b);
    
    a -> R24
    b -> R22
    return -> R24
    
    struct largeStructure someFunction2(byte a, byte b);
    
    a -> R22 (instead of R24)
    b -> R20 (instead of R22)
    address of tmp_mem -> R25:R24
    return -> in memory tmp_mem
    

    If the value returned is up to 8 bytes long the value is returned in the following registers:

    1 byte: R24
    2 bytes: R24...R25
    3 bytes: R22...R24
    4 bytes: R22...R25
    5 bytes: R20...R24
    6 bytes: R20...R25
    7 bytes: R18...R24
    8 bytes: R18...R25