在链接一些对类型long long
I 的整数执行除法和模运算的代码时,会收到以下两个错误:
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
当为不为GCC用作[ unsigned
] 的数据类型提供硬件支持的体系结构构建代码时long long
,GCC为该类型的值生成算术运算的代码,该代码涉及调用由其自己的支持库提供的函数libgcc
.在__divdi3()
等那些之中.这不是GCC可以做到的唯一方式,但它非常适合GCC支持许多架构的目标.
当被指示充当独立编译器时,GCC不会自动链接libgcc,结果是不会自动提供这些函数的实现.这一直是以前投诉的主题,例如这个和后来的投诉.GCC维护者采取的立场是,这不是GCC的缺陷,并且它不会使GCC不符合要求.我觉得他们的推理有问题,但不太可能改变.至少,这是一个实施质量问题.
我确实看到了GCC维护者的来源,但是:独立环境几乎不提供标准库,并且除了根据提供给它的代码之外,不得解释大多数函数调用.那么,如果该代码包含对与libgcc中某些函数具有相同名称的函数的显式调用,那该怎么办?除非用户明确表示他想要libgcc,否则编译器不应该假设它是所需函数的那些版本.但问题是,如果编译器插入这样的调用,那么它不仅知道哪些实现是预期的,而且如果链接了不兼容的实现,则结果是错误的.因此,这是海湾合作委员会自己制定的问题.
底线是您可以明确请求链接libgcc.您将需要指定它是静态链接的,因为您不能依赖上下文中的动态链接器.这些额外的链接选项应该这样做:
-static-libgcc -lgcc
或者,您可以编写自己的这些函数的实现,或者从GCC中获取源代码,但我不明白为什么您更喜欢这些选项.