2013-08-26 3 views
1

gcc은 하드웨어에서 지원되지 않는 정수 유형의 곱셈 또는 나눗셈을 볼 때 특수 라이브러리 함수를 호출합니다.x86에서 gcc가 long으로 long으로 사용하는 divdi3 division

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는 "하나의 서명 된 더블 워드의 분할 요청"이라고 설명했습니다. 첫번째 소스가 디 접미사의 클리 어리 매핑이있는 경우 -> 긴 인수, 둘째 주 (오른쪽, 단일?) 풀 단어를 udivdi을 두 번 단어를 divdi 및

내가 함께 간단한 예

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 버전. 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를 사용할 수없고 멀티 플랫폼입니다. 나는 모든 플랫폼에 대해 모든 __* 함수를 쓰지 않기를 바랬는데 (속도는 중요하지 않음), 이제는 다소 혼란 스럽다.

누군가가 설명 할 이유가 (__divti3되지 않음) long long int (64 비트) 부문에 대해 생성 호출 __divdi3?

답변

2

단어가 없습니다. x86 시스템에서 word는 보통 16 비트를 의미합니다. 관습입니다. 일반적으로 word은 활성화 된 모드 (실제 또는 보호 된)에 따라 너비가 달라지는 16 비트 또는 32 비트 숫자입니다.

나는 리눅스/유닉스가 일반적으로 많은 플랫폼에서 실행되기 때문에이 용어가 사용되었다고 생각한다. 더 많은 도구에서 용어의 충돌을 느낄 수 있습니다. 라이브 예제는 gdb이며 32 비트 단어는 w이고 16 비트 "하프 워드"는 hw입니다.

편집 : float의 크기에는 다른 이름이 사용되지만 정수에도 사용됩니다. 그것은이다 :

  • s - 더블 (정밀) 팔 개 바이트 정수 (long 또는 long long)/수레 - 네 바이트 정수 (int)/수레 (float)
  • d에 대한 단일 (정밀, 단어?) (double)
  • t - 정수의 열 바이트 (long long)/수레 (long double)

이 이름은 __divsi3, __divdi3, __divti3 또는 __mulsi3, __muldi3, __multi3 ... (모두 u - 부호없는 변형)과 같은 모든 산술 연산에 사용됩니다. 그것이 __divdi3의 이유입니다. 전체 목록은 on this page입니다.

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

고마워요. 나는 그 게시물을 고쳤다. 질문은 algorythm이 아니라 관례입니다. 나는'__divti3' 호출을 볼 것으로 예상했지만 거기에는'__divdi3'가 있습니다. – user2718551

+0

수정되었습니다. – user35443

+0

고마워,하지만'd'가''long' **이나 **'long long'을위한 이유는 아직 불분명하다. 게시자가 제공하는 소스가 게시물의 첫 번째 링크입니다. 'd'는'long ','t'는'long long'을위한 옵션이없는 상태입니다. 몇 가지 변형이있을 수 있는데 왜'd'가 선택되고't'가 아닌가? – user2718551

관련 문제