1

On my raspberry-pi I have two files: main.s and file.c.
file.c contains a function called foo that prints the floating-point number 1.4

#include <stdio.h>
void foo(){
    double a = 1.4;
    printf("%f\n", a);
}

main.s contains a main-function that calls foo and returns 0

    .global main
main:
    push {lr}
    bl foo
    mov r0, #0
    pop {pc}

When I compile and run the program it prints a garbage decimal number.

$ gcc file.c main.s -o a
$ ./a
190359901426432118378104432082065795719817104605055420380549740704558175549767996835670175700923114787186017481619470916538605140186901692001326762660598893470884230006875222134524739584.000000

However if I change main.s to

    .global main
main:
    push {r4, lr}
    bl foo
    mov r0, #0
    pop {r4, pc}

it works as expected

$ gcc file.c main.s -o b
$ ./b
1.400000

Why does the main-function need to push r4 for printf to work correctly?

(Compiling the main-function written in C produces the assembly that works, which is how I found it.)

Jonatan
  • 21
  • 4
  • Side note, you should use %lf for doubles as listed [here](https://cplusplus.com/reference/cstdio/printf/) – Frazzo Jun 14 '22 at 10:16
  • 5
    @Frazzo I don't know where you read this but that is wrong. floats are promoted to double when they are passed to variadic functions. https://en.cppreference.com/w/cpp/language/variadic_arguments I think you confuse this with scanf where ```%lf``` does indeed specify pointer to double instead of ```%f```'s pointer to float – Homer512 Jun 14 '22 at 10:21
  • 2
    I think this issue describes your problem: https://github.com/zephyrproject-rtos/zephyr/issues/2108 The stack needs to be aligned to 8 byte boundaries on function entry. Pushing one 32bit register gives you only 4 byte alignment – Homer512 Jun 14 '22 at 10:23
  • @AdrianMole: That definitely wasn't the right duplicate (I edited the duplicate list). Note that the call to printf is being made from a compiled C function, not hand-written asm. And the arg is a constant, not coming from args passed by asm. And despite the title, it's a `double`, not a `float`, so no implicit promotion is even needed. I'm a bit curious exactly why stack misalignment could cause *this* specific problem, but that's what I assumed it was going to be from the title. – Peter Cordes Jun 14 '22 at 11:37
  • @Peter Yeah - I was misled by the title and comments. Thanks for correcting the error. – Adrian Mole Jun 14 '22 at 13:09

1 Answers1

1

from comments:

I think this issue describes your problem: github.com/zephyrproject-rtos/zephyr/issues/2108 The stack needs to be aligned to 8 byte boundaries on function entry. Pushing one 32bit register gives you only 4 byte alignment

Jonatan
  • 21
  • 4