Linux 加载警告:找不到输入符号\u start
我在学习汇编编程。下面是打印“你好,世界!”的简单程序。程序运行正常时,我在加载时收到警告消息 ld:警告:找不到输入符号\u start;默认为000000000 8048080 代码如下:Linux 加载警告:找不到输入符号\u start,linux,assembly,warnings,nasm,ld,Linux,Assembly,Warnings,Nasm,Ld,我在学习汇编编程。下面是打印“你好,世界!”的简单程序。程序运行正常时,我在加载时收到警告消息 ld:警告:找不到输入符号\u start;默认为000000000 8048080 代码如下: section .data msg db 'Hello, world!', 0xa len equ $ - msg section .text global main main: mov ebx, 1 mov ecx, msg mov edx, len
section .data
msg db 'Hello, world!', 0xa
len equ $ - msg
section .text
global main
main:
mov ebx, 1
mov ecx, msg
mov edx, len
mov eax, 4
int 0x80
mov eax, 1
int 0x80
谁能解释一下这个警告的含义吗。我正在将
nasm
与ubuntu14
一起使用 使用标签\u start
而不是main
作为ELF入口点。main
意味着它类似于Cmain
函数,但它甚至不是一个函数(例如)
您没有说,但根据错误消息和代码,我假设您正在使用
nasm-felf32 hello32.asm&&ld-melf_i386-o hello32 hello32.o构建32位代码
(如果您实际构建的是64位代码,那么幸运的是它正好工作,但只要您使用esp
而不是rsp
执行任何操作,它就会崩溃)
错误消息来自ld
,而不是来自nasm
。这句话在信息里说得很对。Tim的评论是正确的:ld
在它链接的文件中查找\u start
符号,但如果没有找到,则将入口点设置为文本段的开头
您定义的其他全局/外部符号并不重要main
在这里没有任何关联,可以指向任何你想要的地方。它只对反汇编输出和类似的东西有用。如果取出global main
/main:
行,或者将它们更改为任何其他名称,则代码的工作原理完全相同
将其标记为main
是不明智的,因为ELF入口点不是函数。它不是main()
,不接收argc
和argv
参数,也不能ret
,因为ESP指向的是argc
,而不是返回地址
仅当您链接到gcc/glibc的CRT启动代码,该代码查找main
符号并在初始化libc后调用它时,才使用main
。(所以像printf这样的函数可以工作。技术上,动态链接器钩子允许libc在\u启动之前进行初始化,如果您链接了它,但通常不会这样做,除非您完全理解自己在做什么)。相关的:
e、 g.gcc-m32-o hello main.o
如果定义了main:
而不是gcc-m32-static-nostlib-o hello start.o
(这相当于您的裸ld
)。我建议您将对象文件(无论它们是如何生成的)链接到gcc
,而不是ld
gcc
将使用适当的选项调用ld
,因为它了解更多关于源代码的信息,并将创建ld
所做假设所需的任何内容。您可以尝试使用nasm编译程序集源文件,生成*.o文件,然后使用ld链接带有参数-e main的*.o文件。这意味着main被指定为程序条目。您应该使用_start来指示nasm汇编程序应该从哪里开始执行。
例如:
您的程序中存在一些问题,例如
一些语法错误,比如不能将寄存器的值赋给常量,因为常量不能保存任何值,为了存储常量值,我们使用变量
在汇编程序时,我遇到了下面提到的可接受的时间错误
没有这样的指令:msg db 72ello,world!440xa'
assign.S:3:错误:没有这样的指令:
leneq$-msg'
assign.S:4:错误:没有此类指令:section.text'
assign.S:5:错误:没有此类指令:
global main'
assign.S:7:错误:mov'的内存引用过多
assign.S:8:错误:mov的内存引用过多
assign.S:9:错误:mov'的内存引用过多
assign.S:10:错误:mov的内存引用过多
assign.S:11:错误:int'的操作数大小不匹配
assign.S:12:错误:mov的内存引用过多
assign.S:13:错误:“int”的操作数大小不匹配
下面的代码在32位英特尔处理器的gnu编译器上提供相同的输出
.第节.罗达
msgp:
.字符串“Hello World”
用最新名称保存此代码take Hello.S
赞同
$as-o你好。o你好。S
联系
$ld-o Hello.o-lc-dynamiclinker/lib.ld.linux.so.2-emain-Hello.o
运行
美元/你好
希望它能帮助您编译和执行您可以创建的bash
脚本,如下所示:
编译64.sh
!/bin//bash
echo "Assembling with Nasm"
nasm -f elf64 -o $1.o $1.asm
echo "Linking ... "
gcc -o $1 $1.o
echo "Done !"
$ ./compile64 nameOftheFile (without extension)
我不知道这是否是一个有效的解决方案,但似乎对我有效:
尝试使用选项
--entry main
链接内核C代码时
ld -o kernel.bin -Ttext 0x1000 kernel_entry.o kernel.o --oformat binary --entry main
我不是汇编专家,但我相信汇编程序正在寻找一个名为\u start
的入口点(它找不到,因为它不在那里)。堆栈溢出似乎已经很成熟,有很多类似的问题,所以请四处搜索。@TimBiegeleisen实际上我也这么认为。但我不明白的是为什么它与main
一起工作。如果要显式地启动,为什么要通过警告而不是错误执行nasm
。我在谷歌上搜索了一下,发现每个人都在他们的汇编代码中使用start\uu
关键字,但为什么它使用main
关键字。“为什么nasm通过警告而不是错误”。从我所看到的警告来自链接器,而不是nasm。链接器找不到入口点,因此它可能默认为.text
部分的开头。相关:事实上,在我使用的教程中,他们使用了main
而不是start\ucode>@Atinesh:那么您应该使用gcc-m32-o hello32.o
来构建,而不是
--entry main
ld -o kernel.bin -Ttext 0x1000 kernel_entry.o kernel.o --oformat binary --entry main