3

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;
}

with 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

4

1 回答 1

4

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

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

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

  • s- single (precision, word) 用于四字节整数 ( int) / 浮点数 ( float)
  • d- 八字节整数(longlong long)/浮点数(double)的双精度(精度)
  • t- 十个字节的整数 ( long long) / 浮点数 ( long double)

此命名约定用于所有算术内置函数,例如__divsi3, __divdi3, __divti3or __mulsi3, __muldi3, __multi3... (以及所有u- 无符号 - 变体)。可在此处找到完整列表。

32 位机器上的 64 位数字除法使用高级(且有点困难)算法。但是,您仍然可以使用您在学校学到的算法原理。这是它的简单伪代码(看看这个关于大整数的答案):

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--;
}
于 2013-08-26T17:35:48.603 回答