Pergunta

Eu estou tentando compreender algumas montagem.

O conjunto da seguinte forma, estou interessado na linha testl:

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

Eu estou tentando compreender esse ponto de testl entre %eax e %eax? Eu acho que os detalhes do que este código não é importante, estou apenas tentando entender o teste com ele mesmo? - não o valor ser sempre verdadeira

Foi útil?

Solução

Testa se eax é 0, ou acima, ou abaixo. Neste caso, o salto é tomado se eax é 0.

Outras dicas

O significado de test é e os argumentos juntos, e verificar o resultado para zero. Portanto, este código testa se EAX é zero ou não. je pulará se zero.

BTW, isso gera uma instrução menor que cmp eax, 0 que é a razão que compiladores geralmente vai fazê-lo desta forma.

A instrução de teste faz um E-operação lógica entre os operandos, mas não escrever a parte de trás resultado em um registrador. Apenas as bandeiras são atualizados.

No seu exemplo o eax teste, eax irá definir o sinalizador zero se eax é zero, o sinal-bandeira, se o conjunto de bits mais alta e algumas outras bandeiras também.

O Salta se Equal (je) instrução salta se o flag zero é definido.

Você pode traduzir o código para um código mais legível assim:

cmp eax, 0
je  somewhere

Isso tem a mesma funcionalidade, mas requer alguns bytes mais código-espaço. Essa é a razão por que o compilador emitido um teste em vez de uma comparação.

test é como and , exceto que ele só escreve bandeiras, deixando ambas as suas entradas não modificada. Com dois diferentes entradas, é útil para testar se alguns bits são todos zero, ou se pelo menos um está definido. (Por exemplo test al, 3 define ZF se EAX é um múltiplo de quatro (e, portanto, tem tanto ao seu baixo 2 bits zero).


test eax,eax define todas as bandeiras exatamente da mesma maneira que cmp eax, 0 faria :

  • CF e do cancelado (E / TEST sempre faz isso, e subtraindo zero, nunca produz um carry)
  • ZF, SF e PF acordo com o valor em EAX. (a = a&a = a-0)

(excepto para o obsoleto AF (bandeira auxiliar-transporte, utilizado por instruções ASCII / BCD). folhas testá-lo indefinido , mas CMP define que "de acordo com o resultado" . desde subtraindo zero não pode produzir um transporte a partir do 4 a 5 de bit, CMP deve sempre clara AF).


TEST é menor (não imediata) e, por vezes mais rápido (lata macro-fusível em um uop comparar-e-filial em mais CPUs em mais casos do que CMP). que faz test o idioma preferido para testar um registo para zero ou não .

A única razão comum para o uso CMP com um imediato 0 é quando você deseja comparar com uma memória operando (por exemplo, cmpb $0, (%esi) para verificar se há um byte zero terminador no final de uma cadeia de estilo C implícita de comprimento).


AVX512F acrescenta kortestw k1, k2 e AVX512DQ / BW (Skylake mas não KNL) adicionar ktestb/w/d/q k1, k2 , que operam nos registos máscara AVX512 (k0 ..k7), mas ainda definir sinalizadores regulares como test faz, da mesma forma que OR inteiro ou AND instruções fazer.

kortestw k1,k1 é a maneira idiomática para filial / cmovcc / setcc baseado em um resultado comparar AVX512, substituindo SSE / AVX2 (v)pmovmskb/ps/pd + test ou cmp.


Uso de jz vs. je pode ser confuso.

jz e je são, literalmente, a mesma instrução , ou seja, o mesmo código de operação na máquina código. Eles fazem a mesma coisa, mas têm significado semântico diferente para os seres humanos . Disassemblers (e saída normalmente asm de compiladores) será sempre apenas usar um, então a distinção semântica está perdido.

cmp e sub definido ZF quando as suas duas entradas são iguais (isto é, o resultado da subtração é 0). je (salto se igual) é o sinônimo semanticamente relevante.

test %eax,%eax / and %eax,%eax novamente define ZF quando o resultado é zero, mas não há nenhum teste de "igualdade". ZF após o teste não lhe diz se os dois operandos são iguais. Então jz (salto se zero) é o sinônimo semanticamente relevante.

Este trecho de código é a partir de uma sub-rotina que foi dado um ponteiro para alguma coisa, provavelmente alguma estrutura ou objeto. O 2º dereferences de linha que ponteiro, buscar um valor daquela coisa - possivelmente em si um ponteiro ou talvez apenas um int, armazenado como seu 2º membro (offset +4). A 3ª e 4ª linhas testar este valor para zero (NULL se é um ponteiro) e ignorar as seguintes poucas operações (não mostrado) se é zero.

O teste para zero, por vezes, é codificado como comparar com um valor imediato literal zero, mas o compilador (ou humana?), Que escreveu este poderia ter pensado um op testl iria correr mais rápido - levando em consideração tudo o moderno material CPU como pipelining e renomeação de registradores. É a partir do mesmo saco de truques que mantém a idéia de limpar um registo com XOR EAX, EAX (que eu vi na placa de licença de alguém em Colorado!) Em vez do óbvio, mas talvez mais lento MOV EAX, # 0 (i usar uma notação mais velha ).

Em asm, como perl, TMTOWTDI.

Se eax é zero ele irá executar o salto condicional, caso contrário ele irá continuar a execução em 319e9

Em alguns programas podem ser usados ??para verificar se há um estouro de buffer. No topo do espaço alocado a 0 é colocado. Depois de introduzir os dados na pilha, ele procura o 0 no início do espaço alocado para garantir que o espaço alocado não está transbordou.

Foi usado no exercício stack0 de exploits exercícios para verificar se ele foi transbordou e se não dava e não havia um zero lá, ele iria mostrar "Tente novamente"

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

pudemos ver a jg , jle Se testl %edx,%edx. jle .L3we poderia fácil encontrar jle é terno (SF^OF)|ZF, if% edx é zero, ZF = 1, mas se% edx não é zero e é -1, após a testl, a OF = 0, eo SF = 1, então a bandeira = true, que implementam salto .sorry, meu Inglês é pobre

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top