简体   繁体   中英

Getting length of string in NASM with strlen call

My aim is to do the following:

1) Write a nasm code that calculates the length of a string by calling strlen from C

2) Call this function in C to print the length of a supplied string

Nasm code:

    ;nasm -f elf32 getLength.asm -o getLength.o


segment .text
extern strlen
global getLength

getLength:
    push    ebp                 ;save the old base pointer value
    mov     ebp,esp             ;base pointer <- stack pointer

    mov     eax,[ebp+8]         ;first argument
    call    strlen              ; call our function to calculate the length of the string

    mov         edx, eax            ; our function leaves the result in EAX
    pop ebp
    ret

C code:

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

int getLength(char *str);

int main(void)
{
    char str[256];
    int l;

    printf("Enter string: ");
    scanf("%s" , str) ;
    //l = strlen(str);
    l = getLength(str);
    printf("The length is: %d\n", l);
    return 0;
}

I try to compile, link and run as follows:

1) nasm -f elf32 getLength.asm -o getLength.o

2) gcc -c length.c -o getLength.o -m32

3)gcc getLength.o getLength.o -o length -m32

The error I get:

getLength.o: In function `getLength':
getLength.asm:(.text+0x0): multiple definition of `getLength'
getLength.o:getLength.asm:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib32/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status

You overwrite the getLength.o from NASM with gcc -c length.c -o getLength.o -m32 . Just take another name for the output of GCC:

  1. nasm -f elf32 getLength.asm -o getLength.o
  2. gcc -c length.c -o length.o -m32
  3. gcc length.o getLength.o -o length -m32

GCC is smart enough, that you can collapse step 2. and 3.:

2+3. gcc length.c getLength.o -o length -m32

You forgot to pass an argument to strlen and to clear the stack afterwards:

getLength:
    push    ebp                 ;save the old base pointer value
    mov     ebp,esp             ;base pointer <- stack pointer

    mov     eax,[ebp+8]         ;first argument
    push eax                    ; first argument onto the stack
    call    strlen              ; call our function to calculate the length of the string
    add esp, 4                  ; clear stack after C-call

    mov         edx, eax            ; our function leaves the result in EAX
    pop ebp
    ret

There are left some superfluous instructions. Please check, if you really need them.

Judging from the error you get, it would seem you compiled the C file before the ASM file, not after as you described.

To complicate things, the resulting object files will have the same filename. Since you compiled the ASM file last, getLength.o is the compiled ASM file.

The result is that you're trying to link multiple functions named getLength (from the ASM file) and you don't have a main function to link at all.

You can fix it by using different names for the object files (eg length.o for the C file and getLength.o for the ASM file):

gcc -c length.c -o length.o -m32
nasm -f elf32 getLength.asm -o getLength.o
gcc length.o getLength.o -o length -m32

By the way, your getLength function appears to be incorrect:

  1. You forgot to move the argument to strlen onto the stack. push eax before calling strlen .
  2. You moved the return value from eax into edx after calling strlen . This shouldn't be necessary since eax will already have the correct value.
  3. Because you need to push eax , you also need to restore the stack pointer after strlen returns. You can either use add esp, 4 or mov esp, ebp to accomplish this, but it must be done before you pop ebp .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM