2017-04-13 3 views
0

Wie kann ich für das niedrigstwertige Bit testen, die nicht gesetzt ist, wenn ich eine ganze Zahl N. Mein erster Versuch (Gas-Syntax) gegeben bin:wie Bits einer ganzen Zahl in Assembly testen

Sie
#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

Umkehren mit 'nicht', dann' bsf'? – Michael

+0

@Michael, Nein! weil ** das ** eine undefinierte Ausgabe ergibt, wenn die Eingabe -1 ist. – Johan

+0

@Johan: Scheint mir wie 'ZF' könnte verwendet werden, um das zu erkennen. – Michael

Antwort

3

können testen die lsb gesetztbsf (Bit-scan vorwärts) oder noch besser mit tzcnt
mit ich hoffe, Sie sich der Tatsache bewusst sind, dass bsf undefinierte Daten angezeigt werden können, wenn der Operand null ist. tzcnt behebt das.
Wenn Sie das LSB testen möchten, das nicht gesetzt ist, invertieren Sie einfach die Eingabe mit not und dann für die LSB-Set testen.

Beachten Sie, dass tzcnt sowohl (fast) rückwärtskompatibel als auch schneller als bsf ist. tzcnt wird durch eine alte CPU als rep bsf reg,reg gelesen werden, ändert jedoch tzcnt die Fahnen anders bsf:

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

Die beste Lösung tzcnt zu verwenden ist, aber stellen Sie sicher, dass Sie getestet haben, dass die CPU tzcnt (oder unterstützt wird eine bsf ausführen und Ihr Code wird falsche Ergebnisse geben). Die andere Alternative besteht darin, zu testen, ob der Operand Null ist, und entsprechend anzupassen.

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

bsftut ändern Sie die Flags korrekt, können Sie das verwenden, um zu kompensieren.

Von: http://www.felixcloutier.com/x86/BSF.html

BSF ..... Flags Betroffene

Die ZF-Flag auf 1 gesetzt, wenn alle der Quelloperand ist 0;

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

Beachten Sie, dass als grundsätzlich ich nicht schreiben AT & T-Syntax, werden Sie die Operanden gegebenenfalls umkehren müssen.

tzcnt runs a lot faster than bsf (weil die CPU nicht muss nicht undefinierte Verhalten Emulation tun).

+1

Sie müssen sich manchmal stellen, und das ist ein guter Grundsatz, auf dem Sie stehen. –

+0

War nicht in Frage, aber nur zu meinem Spaß, um das am wenigsten signifikante unscharfe Bit als Bitmaske zu extrahieren: 'lea edx, [eax + 1]' 'und eax, edx'' oder eax, edx' (nicht sicher, ob das ist besser als "tzcnt" + Aufbau der Maske aus dem Ergebnis, aber dieses ist 80386 kompatibel (ja, ich steckte in dieser Zeit)). – Ped7g

Verwandte Themen