`testl` eax contra eax?


Estoy tratando de entender alguna asamblea.

La asamblea de la siguiente manera, estoy interesado en la línea testl:

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

Estoy tratando de entender ese punto de testl entre %eax y %eax? Creo que los detalles de lo que este código no es importante, solo estoy tratando de entender la prueba consigo mismo - ¿no sería el valor siempre verdadero?

Author: Michael Petch, 2008-09-29

8 answers

Prueba si eax es 0, o superior, o inferior. En este caso, el salto se realiza si eax es 0.

 75
Author: Chris Jester-Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-09 01:08:52

El significado de test es a y los argumentos juntos, y compruebe el resultado para cero. Así que este código prueba si EAX es cero o no. je saltará si es cero.

Por cierto, esto genera una instrucción más pequeña que cmp eax, 0 que es la razón por la que los compiladores generalmente lo hacen de esta manera.

 83
Author: phuclv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-28 03:57:08

La instrucción de prueba hace una operación AND lógica entre los operandos pero no escribe el resultado de nuevo en un registro. Solo se actualizan las banderas.

En su ejemplo la prueba eax, eax establecerá la bandera cero si eax es cero, la bandera de signo si el bit más alto establecido y algunas otras banderas también.

La instrucción Jump if Equal (je) salta si se establece la bandera cero.

Puede traducir el código a un código más legible como este:

cmp eax, 0
je  somewhere

Que tiene lo mismo funcionalidad, pero requiere algunos bytes más espacio de código. Esa es la razón por la que el compilador emitió una prueba en lugar de una comparación.

 32
Author: Nils Pipenbrinck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 01:29:03

test es como and, excepto que solo escribe BANDERAS, dejando ambas entradas sin modificar. Con dos diferentes entradas, es útil para probar si algunos bits son todos cero, o si al menos uno está establecido. (por ejemplo, test al, 3 establece ZF si EAX es un múltiplo de 4 (y por lo tanto tiene sus dos bits bajos a cero).


test eax,eax establece todas las banderas exactamente de la misma manera que cmp eax, 0 :

  • CF y DE cleared (Y / ENSAYO siempre hace eso; y restando cero nunca produce un acarreo)
  • ZF, SF y PF según el valor en EAX. (a = a&a = a-0)

(Excepto por el obsoleto AF (auxiliary-carry flag, usado por las instrucciones ASCII/BCD). TEST lo deja indefinido , pero CMP lo establece "según el resultado". Dado que restar cero no puede producir un carry del 4to al 5to bit, CMP siempre debe borrar AF).


LA PRUEBA es más pequeña (no inmediata) y a veces más rápida (puede macro-fusionarse en un uop de comparación y rama en más CPU en más casos que CMP). Que hace test el idioma preferido para probar un registro para cero o no.

La única razón común para usar CMP con un 0 inmediato es cuando se desea comparar con un operando de memoria (por ejemplo, cmpb $0, (%esi) para comprobar si hay un byte de terminación cero al final de una cadena de estilo C de longitud implícita).


AVX512F añade kortestw k1, k2 y AVX512DQ / BW (Skylake pero no KNL) añadir ktestb/w/d/q k1, k2, que operan en registros de máscara AVX512 (k0..k7) pero aún así establece BANDERAS regulares como test, de la misma manera que lo hacen las instrucciones integer OR o AND.

kortestw k1,k1 es la forma idiomática de branch / cmovcc / setcc basada en un resultado de comparación AVX512, reemplazando SSE / AVX2 (v)pmovmskb/ps/pd + test o cmp.


El Uso de jz vs je puede ser confuso.

jz y je son, literalmente, la misma instrucción, es decir, el el mismo opcode en el código máquina. Hacen lo mismo, pero tienen un significado semántico diferente para los humanos. Los desensambladores (y típicamente la salida asm de los compiladores) solo usarán uno, por lo que la distinción semántica se pierde.

cmp y sub establecer ZF cuando sus dos entradas son iguales (es decir, el resultado de la resta es 0). je (saltar si es igual) es el sinónimo semánticamente relevante.

test %eax,%eax / and %eax,%eax de nuevo establece ZF cuando el resultado es cero, pero no hay " igualdad" prueba. ZF después de la prueba no le dice si los dos operandos eran iguales. Así que jz (saltar si cero) es el sinónimo semánticamente relevante.

 18
Author: Peter Cordes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-16 13:23:35

Este fragmento de código proviene de una subrutina a la que se le dio un puntero a algo, probablemente alguna estructura u objeto. La 2ª línea desreferente ese puntero, obteniendo un valor de esa cosa - posiblemente en sí mismo un puntero o tal vez solo un int, almacenado como su 2º miembro (offset +4). Las líneas 3ra y 4ta prueban este valor para cero (NULL si es un puntero) y omiten las siguientes operaciones (no mostradas) si es cero.

La prueba de cero a veces se codifica como una comparación con una inmediata valor cero literal, pero el compilador(o humano? quien escribió esto podría haber pensado que una op testl se ejecutaría más rápido, teniendo en cuenta todas las cosas modernas de la CPU, como la canalización y el cambio de nombre del registro. Es de la misma bolsa de trucos que tiene la idea de limpiar un registro con XOR EAX,EAX (que vi en la matrícula de alguien en Colorado!) en lugar del obvio pero quizás más lento MOV EAX, #0 (uso una notación más antigua).

En asm, como perl, TMTOWTDI.

 5
Author: DarenW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 03:40:00

Si eax es cero realizará el salto condicional, de lo contrario continuará la ejecución en 319e9

 3
Author: Mike Thompson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 01:25:07

En algunos programas se pueden usar para comprobar si hay un desbordamiento de búfer. En la parte superior del espacio asignado se coloca un 0. Después de introducir datos en la pila, busca el 0 al principio del espacio asignado para asegurarse de que el espacio asignado no se desborda.

Se usó en el ejercicio stack0 de exploits-ejercicios para verificar si estaba desbordado y si no lo había y había un cero allí, mostraría "Try again"

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
 0
Author: user7259278,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 21:19:36

Pudimos ver el jgjle Si testl %edx,%edx. jle .L3 podríamos encontrar fácilmente jle es suit (SF^OF)|ZF, si %edx es cero ,ZF=1,pero si %edx no es cero y es -1, después del testl, el DE = 0, y el SF =1, por lo que la bandera = true, que implementar salto .lo siento, mi inglés es pobre

 -2
Author: cbei_you,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-14 07:35:26