【问题标题】:Getting length of string in NASM with strlen call使用 strlen 调用获取 NASM 中的字符串长度
【发布时间】:2016-01-01 10:24:33
【问题描述】:

我的目标是做到以下几点:

1) 编写一个 nasm 代码,通过从 C 中调用 strlen 来计算字符串的长度

2) 在 C 中调用此函数以打印提供的字符串的长度

Nasm 代码:​​

    ;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 代码:

#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;
}

我尝试编译、链接和运行如下:

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

我得到的错误:

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

【问题讨论】:

    标签: c linux nasm


    【解决方案1】:

    您用gcc -c length.c -o getLength.o -m32 覆盖来自NASM 的getLength.o。只需为 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 足够聪明,你可以折叠第 2 步和第 3 步:

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

    您忘记将参数传递给 strlen 并在之后清除堆栈:

    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
    

    还有一些多余的说明。如果您真的需要它们,请检查。

    【讨论】:

      【解决方案2】:

      从您得到的错误来看,您似乎在 ASM 文件之前编译了 C 文件,而不是在您描述的之后。

      更复杂的是,生成的目标文件将具有相同的文件名。由于您最后编译了 ASM 文件,所以getLength.o 是编译后的 ASM 文件。

      结果是您尝试链接多个名为 getLength(来自 ASM 文件)的函数,而您根本没有要链接的 main 函数。

      您可以通过对目标文件使用不同的名称来修复它(例如,length.o 用于 C 文件,getLength.o 用于 ASM 文件):

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

      顺便说一句,您的getLength 函数似乎不正确:

      1. 您忘记将strlen 的参数移到堆栈上。 push eax 在调用 strlen 之前。
      2. 在调用strlen 后,您将返回值从eax 移动到edx。这应该不是必需的,因为 eax 已经具有正确的值。
      3. 因为需要push eax,所以还需要在strlen返回后恢复栈指针。您可以使用add esp, 4mov esp, ebp 来完成此操作,但必须在pop ebp 之前完成。

      【讨论】:

      • 是的。那就是编译技巧!但是,我的 NASM 代码中似乎存在某种错误,因为结果为 0。
      • 完美!非常感谢。
      猜你喜欢
      • 2015-03-16
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 2019-03-11
      • 2011-09-22
      • 2011-05-08
      • 2016-03-05
      相关资源
      最近更新 更多