1

assembly code:

section .text
global calculateRoot
extern printFloat

calculateRoot:
    push    rbp                       ; save Base Pointer (bp) original value
    mov     rbp, rsp                  ; use base pointer to access stack contents
    sub rsp, 55                        ; allocating bytes in stack for local variables

    call printFloat

    mov     rsp, rbp                        ; closing stack
    pop     rbp                             ; resotre rbp
    ret

c code:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void printFloat();

extern void calculateRoot(double num);

int main(){
    double num  = 43432432.23532534534543534;
    calculateRoot(num);

    printFloat(num);
    return 0;
}

void printFloat(){
    double h = 4332432525.324324;
    printf("\nFloating Point Number %lf\n",h);
}

The above code produces a segmentation fault. i'm trying to understand why. As i tried to reproduce the problem in different ways, i found out that the seg fault only occurres when i try to print a float. It does not happen with int for example. Furthermore, i found out that different amount in the instruction "sub rsp,55" can fix the problem, i.e if it put 48 or 16 for example there will be no seg fault. Is there something i'm missing here ? Thanks a lot for every answer.

n.p - this code is not meant for anything. i created it when i found out strange things happen in my program. So this code was meant to found my mistake in my real program. And another thing i noticed, when i use 8 in "sub rsp,55" it creates a seg fault, so i created another function in assembly and called it from calculateRoot, in this function i made another "sub rsp,8" and it eliminated the seg fault(16 works when it is used in "sub rsp, 55").

Adam Jensen
  • 49
  • 1
  • 5
  • Have you tried using `gdb` to isolate the issue? – Retr0id Apr 17 '18 at 21:11
  • 1
    55 is not aligned. The stack pointer needs to be aligned to a word boundary, I believe. – Retr0id Apr 17 '18 at 21:13
  • 3
    It actually needs to be 16 byte aligned. – Jester Apr 17 '18 at 21:14
  • @Jester that's an ABI thing, not a hardware thing, right? – Retr0id Apr 17 '18 at 21:15
  • 1
    Yes, ABI. The hardware comes into play because there are instructions which expect alignment and `printf` happens to use those relative to the stack pointer which is assumed aligned. – Jester Apr 17 '18 at 21:16
  • Thx for the quick answers. i did use gdb to find the source, its this line: <__printf+36> movaps XMMWORD PTR [rsp+0x50],xmm0. that the seg fault occurs. i guess i need to use specific subtraction of rsp in order to work with printf correctly then. Thank a lot. – Adam Jensen Apr 17 '18 at 21:41
  • Yep, after one `push`, you need to `sub rsp, n*16`, where `n` is any whole number. Because RSP is 16-byte aligned before `call` pushes a return address, and `push rbp` pushes another 8, bringing you back to aligned. If you don't need to save/restore anything, or have an even number of pushes, then `sub rsp, n*16 + 8` Also don't forget to set `al=1` if you're passing the `double` in xmm0, not on the stack. – Peter Cordes Apr 18 '18 at 04:00
  • The format for printing a double with `printf` is `%f`, not `%lf`. (Although glibc accepts `%lf` as also meaning `double`.) [How to print a single-precision float with printf](//stackoverflow.com/q/37082784) – Peter Cordes Apr 18 '18 at 04:06
  • @PeterCordes thx for the answer, i wrote float as meaning to floating point number, i'm actually working with double so i used %lf and not %f. – Adam Jensen Apr 18 '18 at 16:14
  • Read my last comment again: the format for `double` is `%f`, with `printf` but not `scanf`. If you tried to use `printf %f` for `float` from asm, it would fail. – Peter Cordes Apr 18 '18 at 19:57
  • Update: `%lf` is also correct for `double`, in C99/C11, so you don't need to change now. But if you do ever want to `printf` a `float`, `%f` won't work. – Peter Cordes Apr 18 '18 at 20:31
  • @PeterCordes ok, thx for the info. – Adam Jensen Apr 19 '18 at 02:11

0 Answers0