2013-02-14 67 views
3

只有两个文件main.ckernel.asm,我试图用NASM和GCC编写一个程序。内容如下:在linux中混合使用汇编语言和C编程

的main.c

#include <stdio.h> 

void Print_String() { 
    printf("Hello World!\n"); 
} 

kernle.asm

extern Print_String 

[section .text] 
global _start 
_start: 
    call Print_String 

编译和链接:

nasm -f elf -o kernel.o kernel.asm 
gcc -c -o main.o main.c 
ld -s -lc -o final kernel.o main.o 

然后我运行final文件使用以下命令:./final,但结果是令人沮丧的:

bash: ./final: No such file or directory 

然而,当前目录中确实有文件final,该命令ls,它显示:

final kernel.asm kernel.o main.c main.o 

那么为什么找不到文件final?有什么不对的吗?任何帮助感谢!

+1

你确定它不是一个目录吗? “ls -l”会给你更多的信息。它会告诉你它是否是一个文件,它的大小,它的读/写/执行权限。 – enhzflep 2013-02-14 03:46:20

+0

@enhzflep它确实是一个可执行文件。 'ls -l'显示:'-rwxrwxr-x 1 mycityofsky mycityofsky 1584 Feb 14 11:15 final','mycityofsky'是我的用户名。 – Searene 2013-02-14 03:52:10

+0

'libc'期待'main'被调用,并且期待着一些棘手的启动事情(通过'crt0.o'代码)完成。你不应该使用它,如果没有与'gcc'链接的话 – 2013-02-14 06:49:15

回答

4

这并不是说它本身找不到它。错误信息有点误导。动态链接程序无法解析其依赖关系,因此您的程序映像无法加载(并且不可执行)

问题是,您正在动态链接libc而不使用任何其他工具来实现动态链接。因此,您剩下一个无法加载的二进制图像。

您可能会发现静态链接与libc更容易。这可以按如下方式完成:

ld -Bstatic -o final kernel.o main.o -lc 

注意,您必须在使用它的代码模块main.o之后移动'-lc'位。

如果你试试这个,你会得到一大堆未解决的符号。这是因为您还需要链接libgcc和libgcc_eh。

下面让我相当接近(道歉,在64位系统上工作在这里):

ld -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/32/ -melf_i386 -Bstatic -lc -o final kernel.o main.o -lc -lgcc -lgcc_eh 

这失败我

/usr/lib/gcc/x86_64-linux-gnu/4.4.3/32//libgcc_eh.a(unwind-dw2-fde-glibc.o): In function `_Unwind_Find_FDE': 
(.text+0x193b): undefined reference to `dl_iterate_phdr' 

这并没有太大的意义。您可能会在32位系统上连接32位的运气更多。

更新

道歉上面的漫游。我再次考虑这一点,当然,可以进行动态链接工作。缺少的部分是指定的动态链接:

在我而言,这是:

ld -dynamic-linker /lib32/ld-linux.so.2 -melf_i386 -o final kernel.o main.o -lc 

所以你下面应该工作:

ld -dynamic-linker /lib/ld-linux.so.2 -o final kernel.o main.o -lc 

再次更新

为了回应markzar的评论 - 你必须使系统调用干净地退出。这有类似于C中退出(0)的效果:

mov eax,1 ; Syscall #1  
mov ebx,0 ; Return code 0 = success 
int 80H 
+0

感谢您的详细解答!有用!但它与我之前的想法有点不同。它会显示两个'Hello World!'和一个消息'Segmentation fault(核心转储)':) – Searene 2013-02-14 06:20:09

+0

问题在于你在没有完全退出的情况下濒临世界末日。做一个像这样的系统调用来退出你的程序: mov eax,1 mov ebx,0 int 80H – 2013-02-14 07:06:16

+0

没关系。谢谢! – Searene 2013-02-14 08:23:28

1

试试这个。首先更改kernel.asm如下:

extern Print_String 

[section .text] 
global main 
main: 
    call Print_String 

然后使用下面的命令来创建可执行文件(而不是链接器)。

nasm -f elf -o kernel.o kernel.asm 
gcc -c -o main.o main.c 
gcc -o final kernel.o main.o 
0

很简单:没有main()在程序中调用...所以无论你做什么,在C程序的启动机制没有得到保持。