1

I am new to assembly and I was trying to call an extern function of C within assembly code, I tried to call strlen function as shown in the below code:

global _my_strlen
section .text
extern _strlen

_my_strlen:               ;rdi register has the address of the string that is passed within the main function
    call    _strlen       ;call strlen which is a C function and pass to it rdi
    ret                   ;the return value of strlen is stored in rax and it will be returned to our main

this is my main function:

#include <stdio.h>

int     my_strlen(char *str);

int     main()
{
    printf("len = %d\n",my_strlen("this len must be 19"));
    return (0);
}

however when I compile and run it with nasm, it gives me a segmentation fault as shown below :

[1]    58770 segmentation fault  ./a.out

I searched a little bit, and I found that you should push the stack before calling an extern function and pop it later, so I changed the code like this:

global _my_strlen
section .text
extern _strlen

_my_strlen:
    push    rbp            ;Push stack
    call    _strlen        ;call strlen which is a C function and pass to it rdi
    pop     rbp            ;Pop stack
    ret                    ;the return value of strlen is stored in rax and it will be

and it worked perfectly as shown in the result:

len = 19

I don't know why we need to push the stack, and why it segfaults if you didn't so, what's happening in the background and what has got changed after calling strlen, does calling strlen affect the stack and how?!

Btw I tried to push other registers instead of rbp for example push rdx pop rdx and it worked, and this is making me more confused than before, hope you explain it in a good way, and thanks in advance.

Holy semicolon
  • 868
  • 1
  • 11
  • 27
  • 1
    OS X uses the System V AMD64 ABI. It requires that the stack be aligned at a 16-byte boundary on call. You may want to modify your question given that fact that it can be other registers than `rbp`. Also, a note on terminology, `rbp` is not "the stack". It's typically a pointer to some location in the stack, from which stack-based parameters and local variables have a known offset. The stack is an area in memory. – Thomas Jager Nov 23 '20 at 12:39
  • I still miss where the argument (string) is either placed in a register or is pushed onto the stack. – Paul Ogilvie Nov 23 '20 at 13:01
  • 2
    @PaulOgilvie : In 64-bit code (AMD64 System V ABI) it will be in the register `%rdi`. `%rdi` will be set by the caller of `_my_strlen` and then passed down to the _C_ library `_strlen` – Michael Petch Nov 23 '20 at 13:05

0 Answers0