kae*_*atl 2 c x86 assembly nasm tcc
我有由NASM创建的简单汇编文件.我想把它们联系起来tcc
.为了调试我想printf()
在我的汇编代码中使用.但是当我这样做时,tcc
失败了tcc: undefined symbol 'printf'
.
这是重现错误的最小示例代码:
extern printf
hello: db "Hello world!",0
global main
main:
push hello
call printf
pop eax
ret
Run Code Online (Sandbox Code Playgroud)
安慰:
nasm -felf hello.asm
tcc hello.o
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)tcc: undefined symbol 'printf'
当我使用gcc hello.o
一切正常时,它必须是一个特定的tcc问题.如何使用tcc?
编辑:我正在使用Windows版本的NASM和TCC生成32位Windows可执行文件.
似乎TCC需要关于外部链接的函数的特定类型信息printf
.默认情况下,NASM创建对ELF对象中具有NOTYPE属性的符号的引用.这似乎混淆了TCC,因为它似乎期望外部函数符号用FUNCTION类型标记.
我通过简单的C程序发现了这一点:
#include <stdio.h>
int main()
{
printf ("hello\n");
}
Run Code Online (Sandbox Code Playgroud)
并使用如下命令将其编译为目标文件(TCC默认使用ELF对象):
tcc -c simple.c
Run Code Online (Sandbox Code Playgroud)
这会产生simple.o
.我碰巧使用OBJDUMP来显示汇编代码和ELF头文件.我在代码中没有看到任何异常,但标题中的符号表显示出差异.如果您使用程序READELF,您可以获得符号的详细转储.
readelf -s simple.o
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)Symbol table '.symtab' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS simple.c 2: 00000000 7 OBJECT LOCAL DEFAULT 2 L.0 3: 00000000 26 FUNC GLOBAL DEFAULT 1 main 4: 00000000 0 FUNC GLOBAL DEFAULT UND printf
特别感兴趣的是符号表条目printf
:
Run Code Online (Sandbox Code Playgroud)4: 00000000 0 FUNC GLOBAL DEFAULT UND printf
如果你要为你的对象转储ELF头文件,你hello.o
看起来就像这样:
readelf -s hello.o
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)Symbol table '.symtab' contains 6 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS hello.asm 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 NOTYPE LOCAL DEFAULT 1 hello 4: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf 5: 0000000d 0 NOTYPE GLOBAL DEFAULT 1 main
注意如何符号printf
在hello.o
不同于所述一个在simple.o
上方.默认情况下,NASM使用NOTYPE属性而不是FUNCTION定义标签.
我不知道有什么方法可以解决NASM中的问题,因为我不知道如何强制它在定义为的符号上使用FUNCTION类型而不是NOTYPEextern
.我在十六进制编辑器中更改了类型,并将其链接并按预期运行.
另一种方法是下载YASM(重写NASM).在大多数情况下,NASM和YASM的工作方式相同.YASM的命令行主要与NASM兼容,因此您应该可以将其用作直接替代品.YASM有一个额外的功能,允许您使用type
指令指定符号的类型:
Run Code Online (Sandbox Code Playgroud)9.3.3. TYPE: Set symbol type ELF’s symbol table has the capability of indicating whether a symbol is a function or data. While this can be specified directly in the GLOBAL directive (see Section 9.4), the TYPE directive allows specifying the symbol type for any symbol, including local symbols. The directive takes two parameters; the first parameter is the symbol name, and the second is the symbol type. The symbol type must be either function or object. An unrecognized type will cause a warning to be generated. Example of use: func: ret type func function section .data var dd 4 type var object
您只需为您使用的每个外部函数向汇编代码添加额外的类型信息.您的汇编代码可以修改为:
extern printf
type printf function
hello: db "Hello world!",0
global main
main:
push hello
call printf
pop eax
ret
Run Code Online (Sandbox Code Playgroud)
它应该编译并链接到这个:
yasm -felf hello.asm -o hello.o
tcc hello.o -o hello.exe
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
412 次 |
最近记录: |