Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 尽管使用了gcc链接器,但为程序集代码获取对“\u printf”的未定义引用时出错_Linux_Assembly_X86_Linker_Nasm - Fatal编程技术网

Linux 尽管使用了gcc链接器,但为程序集代码获取对“\u printf”的未定义引用时出错

Linux 尽管使用了gcc链接器,但为程序集代码获取对“\u printf”的未定义引用时出错,linux,assembly,x86,linker,nasm,Linux,Assembly,X86,Linker,Nasm,我试着按照保罗·卡特的《电脑组装》一书中的练习来做 我试图在Ubuntu18上运行1.4第23页的程序。这些文件都可以在上面的github站点上找到 因为原始代码是32位的,所以我使用 nasm-felf32 用于first.asm和asm_io.asm获取对象文件。我还编译了driver.c 我使用gcc中的链接器并运行 gcc -m32 -o first first.o asm_io.o driver.o 但它总是给我一堆错误,比如 对“\u scanf”的未定义引用 对“\u prin

我试着按照保罗·卡特的《电脑组装》一书中的练习来做

我试图在Ubuntu18上运行1.4第23页的程序。这些文件都可以在上面的github站点上找到

因为原始代码是32位的,所以我使用

nasm-felf32

用于first.asm和asm_io.asm获取对象文件。我还编译了driver.c

我使用gcc中的链接器并运行

gcc -m32 -o first first.o asm_io.o driver.o 
但它总是给我一堆错误,比如

对“\u scanf”的未定义引用 对“\u printf”的未定义引用

注意_printf代替printf出现,因为在文件asm_io.asm中进行了一些转换,以保持windows和linux操作系统之间的兼容性

我不知道为什么会出现这些错误。我还尝试直接使用链接器运行

ld -m elf_i386 -e main -o first -first.o driver.o asm_io.o -I /lib/i386-linux-gnu/ld-linux.so.2 
还有许多变化,因为它似乎没有与C库链接

有什么帮助吗?在ELF对象文件1中,从C映射到asm符号名称时,Linux没有在名称前加前缀,这一问题已经讨论了一段时间,并且找不到类似问题的解决方案

所以调用printf,而不是_printf,因为libc中没有_printf

无论兼容代码做了什么,这都是做错了。只有Windows和OS X使用printf,Linux使用printf

因此,要么您配置错误,要么定义了错误的设置,要么它需要更新/移植到Linux

脚注1:在20多年前的古代历史中,带有.out文件格式的Linux确实在符号名上使用了前导下划线

更新:库使用NASM预处理器%定义_scanfscanf等,但它要求您通过与NASM-d ELF_TYPE组合来手动定义ELF_TYPE

他们可能自己检测到ELF32或ELF64输出格式。应该有人提交拉取请求,以使此检测自动进行,代码如下:

%ifidn __OUTPUT_FORMAT__, elf32
  %define  ELF_TYPE 32
%elifidn __OUTPUT_FORMAT__, elf64
  %define  ELF_TYPE 64
%endif


%ifdef ELF_TYPE
...
%endif
在ELF对象文件1中从C映射到asm符号名时,Linux不会在名称前加上前缀

所以调用printf,而不是_printf,因为libc中没有_printf

无论兼容代码做了什么,这都是做错了。只有Windows和OS X使用printf,Linux使用printf

因此,要么您配置错误,要么定义了错误的设置,要么它需要更新/移植到Linux

脚注1:在20多年前的古代历史中,带有.out文件格式的Linux确实在符号名上使用了前导下划线

更新:库使用NASM预处理器%定义_scanfscanf等,但它要求您通过与NASM-d ELF_TYPE组合来手动定义ELF_TYPE

他们可能自己检测到ELF32或ELF64输出格式。应该有人提交拉取请求,以使此检测自动进行,代码如下:

%ifidn __OUTPUT_FORMAT__, elf32
  %define  ELF_TYPE 32
%elifidn __OUTPUT_FORMAT__, elf64
  %define  ELF_TYPE 64
%endif


%ifdef ELF_TYPE
...
%endif

我只是想指出,在asm_io.asm文件中,作者包含了一些用于调试的函数,其中有一个部分%ifdef ELF_TYPE%define\u scanf scanf%define\u printf printf printf,但是我仔细看了一下,在评论中说要用nasm-f ELF-d ELF_TYPE asm_io.asm编译,而且。。。是的,这解决了问题,哈哈,我真蠢。所以我想谢谢你,哈哈,谢谢你迅速的回答。我将把这当作正确的答案answer@ackbar03:他们可以使用%ifidn\uuuuu输出\u格式\uuuu32,还可以检查elf64,以避免您必须在NASM命令行上手动执行任何操作。有人应该发送一个请求。嗯,C库中可能没有printf代码,但为了处理遗留代码,可能应该是:让我们投票支持inclusion!!!:@LuisColorado:我认为,通过为libc和libm中的每个符号使用传统的备用名称,将动态符号表的大小增加一倍,从而降低每个进程启动时的动态链接速度,这是没有任何意义的。你在哪里停?。甚至不可能:_exit2和exit3是独立的函数。请看@PeterCordes,几乎完全一致,您描述的两个问题都可以解决,但我同意您的观点,使特定的实现具有可移植性是一种矛盾。实现有其自身的特殊性。GNU去掉前端标识符的方法允许访问,高级C中没有它的隐藏标识符。引入它的相同标准或推理可以用来消除。我只是想指出,在作者包含的asm_io.asm文件中,包含了一些用于调试的函数,其中有一个部分%ifdef ELF_TYPE%define _scanfscanf printf%define _printf,但是我做了一个简单的修改仔细看,在评论中,它说要用nasm-f elf-d elf_类型asm_io.asm和呃。。。是的,这解决了问题,哈哈,我真蠢。所以我想谢谢你,哈哈,谢谢你迅速的回答。我将把这当作正确的答案answer@ackbar03:他们可以使用%ifidn\uuuuu输出\u格式\uuuuu32,还可以检查elf6
4以避免您必须在NASM命令行上手动执行任何操作。有人应该发送一个请求。嗯,C库中可能没有printf代码,但为了处理遗留代码,可能应该是:让我们投票支持inclusion!!!:@LuisColorado:我认为,通过为libc和libm中的每个符号使用传统的备用名称,将动态符号表的大小增加一倍,从而降低每个进程启动时的动态链接速度,这是没有任何意义的。你在哪里停?。甚至不可能:_exit2和exit3是独立的函数。请看@PeterCordes,几乎完全一致,您描述的两个问题都可以解决,但我同意您的观点,使特定的实现具有可移植性是一种矛盾。实现有其自身的特殊性。去掉前端标识符的GNU方法允许从高级C访问隐藏的标识符,在此之前不使用它。引入它的相同标准或推理可用于消除。将带有-lc参数的C标准库显式包含到编译器中,或链接器显式地将带有-lc参数的C标准库包含到编译器或链接器