2011-08-20 5 views
3

저는 Visual C++ 2008 (9.x)에서 작업하고 있고 DIV 대신에 DIV를 생성하는 컴파일러를 실행할 때 고정 소수점 값을 준비했습니다. IDIV. 코드를 정확히 재현 할 수있는 작은 조각으로 접었습니다.Visual C++은 IDIV (x86, 정수 산술) 대신 DIV를 생성합니다.

short a = -255; 
short divisor16 = 640; // unsigned, 16-bit 
unsigned int divisor32 = 640; // unsigned, 32-bit 
unsigned short s_divisor16 = 640; // signed, 16-bit 
int s_divisor32 = 640; // signed, 32-bit 
int16_t test1 = (a<<8)/divisor16; // == -102, generates IDIV -> OK 
int16_t test2 = (a<<8)/s_divisor16; // == -102, generates IDIV -> OK 
int16_t test3 = (a<<8)/divisor32; // == bogus, generates DIV -> FAIL! 
int16_t test4 = (a<<8)/s_divisor32; // == -102, generates IDIV -> OK 

int bitte_ein_breakpoint=1; 

나는 간단한 분해로 당신을 괴롭히지 않을 것입니다.

이제는 바로 가기를 사용하지 않고 divisor의 형식 (함수 매개 변수 인 unsigned int numPixels)을 변경하는 대신 컴파일러에서 세 번째 (test3) 경우에 DIV를 선택하는 것이 궁금합니다. 서명되지 않은 16 비트 제수로 그렇게하라. 어쨌든 부호없는 산술을 요구할만한 것은 실제로 없다. 적어도 그것은 내가 생각하는 바이며 나는 틀렸다고 희망한다.

+0

Shift는 앞서 말했듯이 산술 대신 논리 인 SHL 명령어를 생성합니다. 그것은 틀린 것처럼 보이지만 * 256은이 부분에서 정확히 동일합니다. – nielsj

답변

7

/ 연산자에 대해 생성 된 코드는 피연산자에 따라 다릅니다.

우선, 식 (a << 8)는 정수 프로모션 피연산자 (ISO C99, 6.5.7p3)의 각각에서 수행되는 다음의 동작은 int 초래하는 int << int이다 때문에 int을 입력 갖는다.

  1. int/short : 오른쪽이 int로 승격, 그러므로 idiv 명령

    지금 네 표현이 있습니다.

  2. int/unsigned short : 오른쪽이 int으로 승격되어 있으므로 idiv 명령으로 승격됩니다.
  3. int/unsigned int : 왼쪽 핸드 사이드는 unsigned int으로 승격되므로 div 명령입니다.
  4. int/int : 아무 것도 승격되지 않으므로, idiv 지시가 적절합니다.

정수 프로모션는 ISO C99의 6.3.1.1p3에 정의되어

int 원래 타입의 모든 값을 나타낼 경우,이 값은 int로 변환된다; 그렇지 않으면 unsigned int으로 변환됩니다. 이를 정수 판촉이라고합니다..

+0

매우 명확합니다, 감사합니다. – nielsj

1

음수 값을 왼쪽으로 시프트하면 정의되지 않은 동작이 발생한다. 따라서 컴파일러가이 시나리오에서 수행하는 작업에서 많은 결론을 이끌어 낼 수 있는지 확신 할 수 없습니다.

+0

이것은 표준에 따라 구현에 따라 다르며 VS8에서 작동합니다. 실제로 asm을 단계별로 실행하고 중간 결과를 확인했습니다. – nielsj

+0

방금 ​​ISO C99 6.5.7p4를 확인했으며 명확히 정의되지 않은 동작 *에 대해 설명합니다. –

+0

저는 MS를 알고 있습니다. 그래서 그들은 '구현에 의존합니다'라고 말합니다. VC는이 특별한 경우에 원하는 * 256을 결과로하는 SHL을 수행합니다. – nielsj