gpt4 book ai didi

c - x86 上的 gcc 使用了 long long 的 divdi3 除法

转载 作者:行者123 更新时间:2023-12-04 02:47:58 26 4
gpt4 key购买 nike

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 (海湾合作委员会版本 4.7.2)拆解给我看

    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 库,而且它是多平台的。我希望不要写所有__*适用于所有平台的功能(速度无关紧要),但现在我有点困惑。

有人可以解释一下,为什么会有__divdi3 (不是 __divti3 )为 long long int 生成的调用(64 位)除法?

最佳答案

在 x86 机器上,术语“字”通常表示存在 16 位值。更一般地,在计算机科学领域,word 可以表示几乎任意长度的值,10 或 12 位的字在嵌入式系统中并不少见。

我认为您偶然发现的术语用于 Linux/Unix 系统只是为了统一操作系统级别,与您构建的目标平台无关。在 gdb 中可以找到使用相同符号的示例,它使用 w 表示 32 位字,使用 hw 表示 16 位字位“半字”(在 x86 意义上)。

此外,该约定还可以轻松扩展到标准 IEEE-754 float ,并在下面的几个要点中进行了总结

  • s - 单(精度,字)用于四字节整数(int)/ float (float)
  • d - 八字节整数(longlong long)/ float (double)的 double (精度) >)
  • t - 十个字节的整数(long long)/ float (long double)

此命名约定用于所有算术内置函数,如 __divsi3__divdi3__divti3__mulsi3__muldi3__multi3...(以及所有 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--;
}

关于c - x86 上的 gcc 使用了 long long 的 divdi3 除法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18448343/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com