我的目标是做到以下几点:
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
答案 0 :(得分:4)
您使用getLength.o
覆盖NASM中的gcc -c length.c -o getLength.o -m32
。只需为GCC的输出取另一个名称:
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
还有一些多余的指示。如果你确实需要,请检查。
答案 1 :(得分:3)
从您得到的错误判断,您似乎在ASM文件之前编译了C文件,而不是在您描述之后。
要使事情复杂化,生成的目标文件将具有相同的文件名。由于您最后编译了ASM文件,因此getLength.o
是已编译的ASM文件。
结果是您尝试链接多个名为getLength
的函数(来自ASM文件),而您根本没有main
函数可以链接。< / p>
您可以通过为目标文件使用不同的名称来修复它(例如,对于C文件为length.o
,对于ASM文件为getLength.o
:
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
功能似乎不正确:
strlen
到堆栈上。在致电push eax
之前strlen
。eax
后将返回值从edx
移至strlen
。这不应该是必要的,因为eax
已经具有正确的值。push eax
,所以还需要在strlen
返回后恢复堆栈指针。您可以使用add esp, 4
或mov esp, ebp
来完成此操作,但必须在pop ebp
之前完成。