조립

2017-04-13 2 views
0
내가 정수 N.에게 내 첫 번째 시도 (가스 구문)을 제공하고있어 만약 내가 해제의 최하위 비트를 테스트하려면 어떻게

의 정수의 비트를 테스트하는 방법 :조립

#define N  %ecx 
#define return %eax 

/* prototype: 
    * int leastSigUnsetBit(unsigned int N) 
    */ 

.text 
.global leastSigUnsetBit 
leastSigUnsetBit: 

movl N, 4(%esp)  

movl $-1, return 
Loop: 
    inc return 
    bt return, N 
    jc Loop 
ret 
+0

'not'와 반전 한 다음 'bsf'를 사용 하시겠습니까? – Michael

+0

@ 마이클, 안돼! 왜냐하면 **는 입력이 -1 일 때 정의되지 않은 출력을 줄 것이기 때문입니다. – Johan

+0

@Johan : ZF가 그것을 탐지하는 데 사용될 수있는 것처럼 보입니다. – Michael

답변

3

당신이 할 수있는 LSB가 이 (앞으로 스캔 비트) bsf를 사용하거나 더 나은 당신이 피연산자가 제로의 경우 bsf가 정의되지 않은 데이터를 반환 할 것이라는 사실을 알고 있습니다 희망 tzcnt
를 사용하여
을 설정 테스트합니다. tzcnt로 수정되었습니다.
의 값이 인 LSB를 테스트하려면 not을 사용하여 입력을 반전 한 다음 LSB 집합을 테스트하십시오.

tzcnt은 (거의) 역 호환되며 bsf보다 빠릅니다. tzcntrep bsf reg,reg로 오래된 CPU에 의해 읽을 수 있습니다, 그러나 tzcnt는 bsf 다르게 플래그를 수정 :

bsf: ZF=0 -> input was 0. 
tzcnt: ZF=0 -> output is 0, CF=0 -> input was zero. 

가장 좋은 해결책은 tzcnt를 사용하지만, 당신이 CPU가 tzcnt을 지원하는지 테스트 한 확인하는 것입니다 (그것이 나 bsf이 실행되고 코드가 잘못된 결과를 표시합니다.

;Intel syntax 
mov eax,not(-1) 
tzcnt edx,eax  ;edx = 32  
mov eax,[random] 
not eax   
tzcnt eax,eax 

다른 대안은 피연산자가 0인지 테스트하고 그에 따라 조정하는 것입니다. bsf이 올바르게 플래그를 변경하면이를 사용하여 보정 할 수 있습니다.

은 사람 : http://www.felixcloutier.com/x86/BSF.html

BSF ..... 플래그는 모든 소스 피연산자가 0이면 ZF 플래그가 1로 설정

영향; 원칙의 문제로 내가 & T의 구문을 쓰지 않는 것이

not eax 
mov edx,32 
bsf eax,eax  
cmovz eax,edx   //force result to 32 if zero inputted. 

주, 당신은 적용 가능한 피연산자를 반대로해야합니다.

tzcnt runs a lot faster than bsf (CPU가 정의되지 않은 동작 에뮬레이션을 수행하지 않기 때문에).

+1

때때로 스탠드를 만들어야합니다. 스탠드를 세우는 좋은 교장입니다. –

+0

문제가되지는 않았지만 재미있는 점은 비트 마스크로 가장 중요하지 않은 비트를 추출하는 것입니다 :'lea edx, [eax + 1]''그리고 eax, edx''xor eax, edx' 'tzcnt'보다 낫다. + 그 결과로 가면을 만든다. 그러나 이것은 80386과 호환된다 (예, 나는 그 시대에 갇혀있다.)). – Ped7g