1

I'm working on a hobby compiler project, and am getting frustrated because my generated assembly makes perfect sense to me but causes a segmentation fault on running. For the input printf("%d", strcmp("1", "2"));, the compiler generates:

    .globl  _main
_main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp

    leaq    S0(%rip), %rax
    movq    %rax, %rdi
    pushq   %rdi
    leaq    S1(%rip), %rax
    movq    %rax, %rdi
    leaq    S2(%rip), %rax
    movq    %rax, %rsi
    callq   _strcmp
    popq    %rdi
    movq    %rax, %rsi
    callq   _printf

    addq    $16, %rsp
    popq    %rbp
    retq

S0:
    .asciz "%d"
S1:
    .asciz "1"
S2:
    .asciz "2"

The compiler starts by generating code to call printf, since that's what it encounters first. However, the second argument is a function call, so I thought it would be a good idea to push all the arguments I've already parsed, hence the pushq %rdi (and later popq %rdi). However, running the program causes a segfault without printing anything, and I'm not sure why. I'm guessing it's either due to stack alignment somehow or it's due to the offset based adressing (leaq S0(%rip), %rax) not being stored or retrieved correctly. Commenting out the instructions that push and pop %rdi and after the call to strcmp re-inserting leaq S0(%rip), %rdi before callq _printf causes the program to run as expected.

I've been banging my head against the wall trying to figure this out. If anyone can help figure out exactly what's wrong with the given assembly, it would be much appreciated.

System info: Working on a 2015 Mac running Mac OSX 10.15.6.

$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.29)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Jester
  • 56,577
  • 4
  • 81
  • 125
Dovahkiin
  • 946
  • 14
  • 25
  • 2
    Yes, you misalign the stack. Also, learn to use a debugger. – Jester Jul 11 '21 at 22:21
  • 4
    You forgot to pass AL=0 since this call to printf has 0 FP args in XMM registers. Use `xor %eax,%eax` right before `call printf`. That's one reason why printf would be using SSE registers, but I think Apple's libc (compiled by clang) aggressively uses aligned xmm load/store to copy stuff around on the stack, and thus will always require stack alignment. – Peter Cordes Jul 11 '21 at 22:57
  • 2
    The more usual way to handle this issue is to move the value into a call-preserved register before the function call: rbx, rbp or r12-r15. This of course means you have to push and pop that register in the prologue and epilogue of your function, and thus you have to align the stack accordingly when you do so, but that's better than doing it on every call you make (especially if it's in a loop). If you run out of call-preserved registers, then allocate a stack slot as for a local variable, and store the value there. – Nate Eldredge Jul 11 '21 at 23:03

0 Answers0