이 코드 스 니펫에서 16 비트 레지스터가 BSR 명령에 사용되는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1818374

  •  10-07-2019
  •  | 
  •  

문제

~ 안에 이 하드 코어 기사 기능이 있습니다 find_maskwidth() 기본적으로 표현하는 데 필요한 비트 수를 감지합니다. itemCount 명령 값 :

unsigned int find_maskwidth( unsigned int itemCount )
{
    unsigned int maskWidth, count = itemCount;
    __asm {
        mov eax, count
        mov ecx, 0
        mov maskWidth, ecx
        dec eax
        bsr cx, ax
        jz next
        inc cx
        mov maskWidth, ecx
    next:
    }
    return maskWidth; 
} 

문제는 그들이 사용하는 이유입니다 ax 그리고 cx 대신 등록 eax 그리고 ecx?

도움이 되었습니까?

해결책

나는 그들이 16 비트 이하의 필드만을 다룰 것으로 기대한다고 생각할 수있다. 패키지의 코어 또는 논리 프로세서 수와 같은 것을보고하는 데 사용할 수있는 비트 수를 결정하는 데 사용되기 때문에 65535 이상으로 넘쳐나 기 전에 시간이 오래 걸릴 것입니다.

나는 누군가가보다 일반적인 목적으로 루틴을 사용하기로 결정하지 않기를 바랍니다.

그리고 FYI- X86 어셈블리로 떨어지지 않고 이와 같은 일을하고 싶다면 (기사의 목적에 대해서는 포트가 불가능하다고 생각하지만), 비트 twiddling 핵 페이지 당신은 덮었습니까?

다른 팁

원래 데이터의 너비는 16 비트에 불과한 것 같습니다. CX는 약간의 숫자를 얻고 있기 때문에 어쨌든 아주 적은 수보다 클 수있을 가능성이 없습니다.

한 레벨에서 16 비트 및 32 비트 IA32의 Opcodes는 접두사 바이트를 제외하고는 동일하므로 어떤 모드에 따라 All-32 또는 All-16 비트 지침을 발행하는 것이 더 효율적입니다. 당신은 들어 왔습니다. 그게 당신이 질문을 한 이유라고 생각합니다 ...

이 코드가 실제로 쓰여지지 않았다는 사실을 감안할 때 (예를 들어 코드를 혼란스럽게하는 것 외에도 마스크 폭과 카운트 변수가 전혀 필요하지 않음) 또 다른 "나쁜 것"임을 확신 할 수 있다고 생각합니다. 이 코드에서.

일상은 기본적으로 ItemCount의 이진 (베이스 2) 로그를 결정합니다.

ItemCount> 2^16 인 경우 완전히 잘못된 값을 제공합니다. 그것은 포화되지 않거나 무언가가 아니며, 단지 명백한 잘못입니다. 입력 매개 변수는 "부호없는 int"이므로 더 잘못된 것입니다. 따라서 더 많은 65536 코어에서 작동을 멈출 것입니다.

내 생각에, 인텔의 누군가가 실제로 16 비트로 거슬러 올라가는 정말 고대 코드를 파고 실제로 이해하지 않고 사용했으며 65536이 영원히 충분히 충분하기 때문에 640k 메모리가 영원히 충분하거나 두 개가되기 때문입니다. -기지 연도는 시간이 끝날 때까지 충분합니다.

이 코드의 저자는 아마도 그가 무엇을하고 있는지 알지 못했을 것입니다 :-). 이 지침의 16 비트 버전은 더 길고 빠르지 않습니다. 실제로, 그들은 아마도 ECX를 사용하는 다음 명령어에서 부분 레지스터 스톨을 일으킬 것입니다 (예 : MOV).

또한 DEC는 출력이 0 일 때 ZF를 이미 설정하므로 점프는 1 월 (DEC 이후)에 하나의 명령을 안전하게 이동할 수 있습니다. 코드를 약간 단순화 할 수 있습니다.

이것이 제가이 코드 스 니펫을 작성하는 방법입니다.

  mov eax, [count]
  xor ecx, ecx
  dec eax
  jz next
  bsr ecx, eax
  inc ecx
next:
  mov [maskWidth], ecx

또한, 여기서 조립에 대한 동기 부여는 BSR 명령을 사용하는 것으로 보이며, 이는 C 언어 나 라이브러리에 해당하지 않습니다. 이 목적을 위해 컴파일러 별 고유 기능을 사용하여 어셈블리를 사용하지 않을 수 있습니다. 이것들은 본질적으로 포송 할 수 없지만 인라인 어셈블리도 아닙니다.

GCC에서 동등한 기능은 다음과 같습니다.

unsigned int find_maskwidth(unsigned int itemCount)
{
   if(itemCount <= 1)
      return 0;
   else
      return 32 - __builtin_clz(itemCount - 1);
}

훨씬 더 읽기 쉬운가요?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top