assembly - Segfault with pop/push in x86/OSX -
i struggling understand why x86 assembly code, compiles fine gcc 4.2.1 (llvm) on osx, gives segmentation fault when executable run:
.globl _main _main: push %rbp mov %rsp, %rbp mov $1, %rbx push %rbx lea l_.str0(%rip), %rdi mov %rbx, %rsi call _printf pop %rbx pop %rbp ret .section __text,__cstring,cstring_literals l_.str0: .asciz "%d \000"
i observed if pop %rbx
line moved before call _printf
, program works correctly. why should fail @ in original form?
this question answered in detail by: how print argv[0] in nasm? , x86 assembly on mac. it's gotcha when programming assembly on macosx.
to summarize:
- this seg fault due stack misalignment.
- this occurs on oses use system v calling convention (including macosx, excluding linux), insists stack pointer multiple of 16 prior making function call (e.g.
printf
).
a simple solution align stack pointer (ie, align multiple of 16 bytes per sys v requirement) prior call, , restore after call:
.globl _main _main: push %rbp mov %rsp, %rbp mov $1, %rbx lea l_.str0(%rip), %rdi mov %rbx, %rsi push %rbx mov %rsp, %rax ; save copy of stack pointer (sp) , $-16, %rsp ; align sp nearest multiple of 16. sub $8, %rsp ; pad sp 8 bytes when ... push %rax ; push saved sp (=8 bytes on 64-bit os), ; remain aligned 16 bytes (8+8 = 16). call _printf pop %rax ; retrieve saved sp mov %rax, %rsp ; restore sp using saved value. pop %rbx pop %rbp ret .section __text,__cstring,cstring_literals l_.str0: .asciz "%d \000"
Comments
Post a Comment