Domanda

Sto cercando di capire un po 'di assemblaggio.

L'assemblaggio come segue, sono interessato alla riga testl :

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

Sto cercando di capire quel punto di testl tra % eax e % eax ? Penso che i dettagli di ciò che questo codice non è importante, sto solo cercando di capire il test con se stesso - il valore non sarebbe sempre vero?

È stato utile?

Soluzione

Verifica se eax è 0, o sopra o sotto. In questo caso, il salto viene eseguito se eax è 0.

Altri suggerimenti

Il significato di test è AND insieme agli argomenti e controlla il risultato per zero. Quindi questo codice verifica se EAX è zero o no. je salterà se zero.

A proposito, questo genera un'istruzione più piccola di cmp eax, 0 , motivo per cui i compilatori generalmente lo faranno in questo modo.

L'istruzione di test esegue un'operazione AND logica tra gli operandi ma non riscrive il risultato in un registro. Vengono aggiornati solo i flag.

Nel tuo esempio il test eax, eax imposterà il flag zero se eax è zero, il segno-flag se il bit più alto impostato e anche alcuni altri flag.

L'istruzione Jump if Equal (je) salta se è impostato il flag zero.

Puoi tradurre il codice in un codice più leggibile come questo:

cmp eax, 0
je  somewhere

Ha le stesse funzionalità ma richiede alcuni byte più spazio di codice. Questo è il motivo per cui il compilatore ha emesso un test anziché un confronto.

test è come e , tranne per il fatto che scrive solo FLAGS, lasciando entrambi i suoi input non modificati. Con due input diversi , è utile per verificare se alcuni bit sono tutti zero o se almeno uno è impostato. (ad es. test al, 3 imposta ZF se EAX è un multiplo di 4 (e quindi ha entrambi i suoi 2 bit bassi azzerati).


test eax, eax imposta tutto contrassegna esattamente allo stesso modo che cmp eax, 0 sarebbe :

  • CF e OF cancellati (AND / TEST lo fa sempre; e sottrarre zero non produce mai un carry)
  • ZF, SF e PF secondo il valore in EAX. ( a = a & amp; a = a-0 )

(Ad eccezione della AF obsoleta (bandiera di trasporto ausiliario, utilizzata dalle istruzioni ASCII / BCD). TEST lo lascia indefinito , ma CMP lo imposta " in base al risultato "


TEST è più piccolo (non immediato) e talvolta più veloce (può fondere macro in un confronto e ramificare su più CPU in più casi di CMP). Questo rende test il linguaggio preferito per testare un registro per zero o no .

L'unico motivo comune per l'utilizzo di CMP con uno 0 immediato è quando si desidera confrontare un operando di memoria (ad esempio, cmpb $ 0, (% esi) per verificare la presenza di un byte zero che termina in la fine di una stringa di tipo C di lunghezza implicita).


AVX512F aggiunge kortestw k1, k2 e AVX512DQ / BW (Skylake ma non KNL) aggiungere ktestb / w / d / q k1, k2 , che funzionano sui registri maschera AVX512 (k0..k7) ma impostano comunque FLAG regolari come test , allo stesso modo che istruzioni integer OR o AND .

kortestw k1, k1 è il modo idiomatico di diramare / cmovcc / setcc basato su un risultato di confronto AVX512, sostituendo SSE / AVX2 (v) pmovmskb / ps / pd + test o cmp .


L'uso di jz rispetto a je può essere fonte di confusione.

jz e je sono letteralmente i stessa istruzione , ovvero lo stesso codice operativo nel codice macchina. Fanno la stessa cosa, ma hanno un significato semantico diverso per gli umani . I disassemblatori (e in genere richiedono output dai compilatori) ne useranno sempre e solo una, quindi la distinzione semantica viene persa.

cmp e sub impostano ZF quando i loro due input sono uguali (ovvero il risultato della sottrazione è 0). je (salta se uguale) è il sinonimo semanticamente rilevante.

test% eax,% eax / e% eax,% eax imposta nuovamente ZF quando il risultato è zero, ma non c'è " uguaglianza " test. ZF dopo il test non ti dice se i due operandi erano uguali. Quindi jz (salta se zero) è il sinonimo semanticamente rilevante.

Questo frammento di codice proviene da una subroutine a cui è stato dato un puntatore a qualcosa, probabilmente una struttura o un oggetto. La seconda riga dereferenzia quel puntatore, recuperando un valore da quella cosa - probabilmente un puntatore o forse solo un int, memorizzato come suo secondo membro (offset +4). La terza e la quarta riga verificano questo valore per zero (NULL se è un puntatore) e salta le seguenti operazioni (non mostrate) se è zero.

Il test per zero a volte è codificato come un confronto con un valore zero letterale immediato, ma il compilatore (o umano?) che ha scritto questo potrebbe aver pensato che un'operazione di test avrebbe funzionato più velocemente - prendendo in considerazione tutte le cose moderne della CPU come pipelining e registrazione della ridenominazione. È dalla stessa serie di trucchi che contiene l'idea di cancellare un registro con XOR EAX, EAX (che ho visto sulla targa di qualcuno in Colorado!) Piuttosto che l'ovvio ma forse più lento MOV EAX, # 0 (uso una notazione più vecchia ).

In asm, come perl, TMTOWTDI.

Se eax è zero eseguirà il salto condizionale, altrimenti continuerà l'esecuzione a 319e9

In alcuni programmi possono essere utilizzati per verificare la presenza di un buffer overflow. Nella parte superiore dello spazio assegnato viene posizionato uno 0. Dopo aver inserito i dati nello stack, cerca lo 0 all'inizio dello spazio allocato per assicurarsi che lo spazio allocato non sia traboccato.

È stato usato nell'esercizio stack0 di exploit-esercizi per verificare se era traboccato e se non c'era e c'era uno zero lì, visualizzava " Riprova "

0x080483f4 <main+0>:    push   ebp
0x080483f5 <main+1>:    mov    ebp,esp
0x080483f7 <main+3>:    and    esp,0xfffffff0
0x080483fa <main+6>:    sub    esp,0x60                     
0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack
0x08048405 <main+17>:   lea    eax,[esp+0x1c]
0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c] 
0x08048415 <main+33>:   test   eax,eax                  ; checks if its zero
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret

potremmo vedere jg & # 65292; jle Se testl% edx,% edx. jle .L3 potremmo facilmente trovare jle è seme (SF ^ OF) | ZF , se% edx è zero, ZF = 1, ma se% edx non è zero ed è -1, dopo il testl, OF = 0 e SF = 1, quindi il flag = true, che implementa il salto .spiacente, il mio inglese è scadente

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top