divdi3分区在x86上使用了gcc

时间:2013-08-26 16:08:22

标签: c gcc x86 biginteger integer-division

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)调用?

1 个答案:

答案 0 :(得分:4)

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

我认为您所使用的术语仅用于Linux / Unix系统,只是为了在操作系统级别进行统一,而与构建的目标平台无关。可以在gdb中找到使用相同表示法的示例,w使用hw表示32位字,s表示16位“半字”(在x86感)。

此外,该惯例也很容易扩展到标准的IEEE-754浮点数,并在下面的几个要点中进行了总结

  • int - 单个(精度,字)用于四个字节的整数(float)/浮点数(d
  • long - 八个字节整数的双精度(精度)(long longdouble)/浮点数(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--;
}