当gcc
看到硬件不支持的整数类型的乘法或除法时,它会生成对特殊库函数的调用。
http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html#Integer-library-routines
根据以上链接,long __divdi3 (long a, long b)
用于分割长。然而,这里http://gcc.gnu.org/onlinedocs/gcc-3.3/gccint/Library-Calls.html divdi解释为“要求划分一个双字签名”。当第一个源具有di后缀的清晰映射时 - >长参数,第二个状态divdi为双字和udivdi为全字(单,右?)
当我编译简单的例子时
int main(int argc, char *argv[]) {
long long t1, t2, tr;
t1 = 1;
t2 = 1;
tr = t1 / t2;
return tr;
}
gcc -Wall -O0 -m32 -march=i386
(gcc ver.4.7.2)
dissamble告诉我
080483cc <main>:
80483cc: 55 push %ebp
80483cd: 89 e5 mov %esp,%ebp
80483cf: 83 e4 f0 and $0xfffffff0,%esp
80483d2: 83 ec 30 sub $0x30,%esp
80483d5: c7 44 24 28 01 00 00 movl $0x1,0x28(%esp)
80483dc: 00
80483dd: c7 44 24 2c 00 00 00 movl $0x0,0x2c(%esp)
80483e4: 00
80483e5: c7 44 24 20 01 00 00 movl $0x1,0x20(%esp)
80483ec: 00
80483ed: c7 44 24 24 00 00 00 movl $0x0,0x24(%esp)
80483f4: 00
80483f5: 8b 44 24 20 mov 0x20(%esp),%eax
80483f9: 8b 54 24 24 mov 0x24(%esp),%edx
80483fd: 89 44 24 08 mov %eax,0x8(%esp)
8048401: 89 54 24 0c mov %edx,0xc(%esp)
8048405: 8b 44 24 28 mov 0x28(%esp),%eax
8048409: 8b 54 24 2c mov 0x2c(%esp),%edx
804840d: 89 04 24 mov %eax,(%esp)
8048410: 89 54 24 04 mov %edx,0x4(%esp)
8048414: e8 17 00 00 00 call 8048430 <__divdi3>
8048419: 89 44 24 18 mov %eax,0x18(%esp)
804841d: 89 54 24 1c mov %edx,0x1c(%esp)
8048421: 8b 44 24 18 mov 0x18(%esp),%eax
8048425: c9 leave
8048426: c3 ret
注意8048414: call 8048430 <__divdi3>
。
我不能将gcc lib用于我的项目,而且它是多平台的。我希望不要为所有平台编写所有__*
函数(速度无关紧要),但现在我有点困惑。
有人可以解释,为什么为__divdi3
(64位)分区生成了__divti3
(不是long long int
)调用?
答案 0 :(得分:4)
在x86机器上,术语“字”通常表示存在16位值。更普遍的是在计算机科学领域,word
可以表示几乎任意长度的值,在嵌入式系统中10或12位的单词并不少见。
我认为您所使用的术语仅用于Linux / Unix系统,只是为了在操作系统级别进行统一,而与构建的目标平台无关。可以在gdb
中找到使用相同表示法的示例,w
使用hw
表示32位字,s
表示16位“半字”(在x86感)。
此外,该惯例也很容易扩展到标准的IEEE-754浮点数,并在下面的几个要点中进行了总结
int
- 单个(精度,字)用于四个字节的整数(float
)/浮点数(d
)long
- 八个字节整数的双精度(精度)(long long
或double
)/浮点数(t
)long long
- 十个字节表示整数(long double
)/浮点数(__divsi3
)此命名约定用于所有算术内置函数,例如__divdi3
,__divti3
,__mulsi3
或__muldi3
,__multi3
,{{1} } ...(和所有u
- 无符号 - 变体)。可以找到完整列表here。
32位计算机上的64位数字划分使用高级(和难点)算法。但是,您仍然可以使用您在学校学到的算法原理。这是一个简单的伪代码(看看this answer关于大整数):
result = 0;
count = 0;
remainder = numerator;
while(highest_bit_of_divisor_not_set) {
divisor = divisor << 1;
count++;
}
while(remainder != 0) {
if(remainder >= divisor) {
remainder = remainder - divisor;
result = result | (1 << count);
}
if(count == 0) {
break;
}
divisor = divisor >> 1;
count--;
}