在链接一些对long long
类型的整数执行除法和模运算的代码时,我收到以下两个错误:
util.c:(.text+0x1af): undefined reference to '__divdi3'
util.c:(.text+0x1ef): undefined reference to '__moddi3'
我也尝试使用unsigned long long
,但这会导致以下错误:
util.c:(.text+0x1af): undefined reference to '__udivdi3'
util.c:(.text+0x1ef): undefined reference to '__umoddi3'
用long long
或int
替换long
可解决问题,但我需要使用unsigned long long
。
我使用以下命令行来编译和链接程序:
gcc -ffreestanding -c kernel/util.c -o kernel/util.o
ld -o kernel32.bin -Ttext 0x500 kernel/util.o kernel/kernel.o --oformat binary
这是功能:
char* itoa(unsigned long long i, char b[]){
if (i == 0){
b[0] = '0';
b[1] = '\0';
return b;
}
char const digit[] = "0123456789";
char* p = b;
if (i < 0){
*p++ = '-';
i *= -1;
}
unsigned long long shifter = i;
while (shifter){
++p;
shifter = shifter / 10;
}
*p = '\0';
while (i){
*--p = digit[i % 10];
i = i / 10;
}
return b;
}
显然,编译器引用__udivdi3
来划分整数,但链接器无法找到它..
顺便说一句,二进制文件将用作32位操作系统,因此缺少许多标准库
编辑:我正在使用gcc 4.8.4和ld 2.24
答案 0 :(得分:13)
为不为GCC用作[unsigned
] long long
的数据类型提供硬件支持的体系结构构建代码时,GCC会为涉及调用函数的该类型的值生成算术运算代码由其自己的支持库libgcc
提供。其中__divdi3()
等等。这不是GCC可以做到的唯一方式,但它非常适合GCC支持许多架构的目标。
当被指示充当独立编译器时,GCC不会自动链接libgcc,结果是不会自动提供这些功能的实现。这是以前投诉的主题,例如this one和this later one。 GCC维护者采取的立场是,这不是GCC的缺陷,并且它不会使GCC不符合要求。我觉得他们的推理有问题,但不太可能改变。至少,这是一个实施质量问题。
我确实看到了GCC维护者的来源,但是:独立环境几乎不提供标准库,并且除了根据提供给它的代码之外,不能解释大多数函数调用。那么,如果该代码包含对与libgcc中某些函数具有相同名称的函数的显式调用,那该怎么办?除非用户明确表示他想要libgcc,否则编译器不应该假设它是所需函数的那些版本。但问题是,如果编译器插入此类调用,那么它不仅知道哪些实现是预期的,而且如果链接了不兼容的实现,则结果是错误的。因此,这是海湾合作委员会自己制定的问题。
最重要的是,您可以明确请求链接libgcc。您将需要指定它是静态链接的,因为您不能依赖上下文中的动态链接器。这些额外的链接选项应该这样做:
-static-libgcc -lgcc
或者,您可以编写自己的这些函数的实现,或者从GCC中获取源代码,但我不明白为什么您更喜欢这些选项。
答案 1 :(得分:0)
根据此链接:https://gcc.gnu.org/onlinedocs/gcc-3.3/gccint/Library-Calls.html
感兴趣的功能在libgcc.a
库中定义。 (不在libgcc.so
库中。)
如果您的链接步骤包含-static
参数
但是,此链接:https://sourceware.org/ml/crossgcc/2006-04/msg00000.html
有以下说法:
通常,您使用gcc而不是ld进行链接,以避免出现这些类型的问题。
我要么使用gcc将其更改为链接,要么添加正确的-L和-l选项以使其使用正确的libgcc
答案 2 :(得分:0)
您似乎使用了错误的功能:
- 运行时函数:long __divdi3(long a,long b)
我猜正确的功能是:
- 运行时功能:long long __divti3(long long a,long long b)
(https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines)
不幸的是我不确定你的gcc版本是否实现了。