A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Informática Numaboa - Tutoriais e Programação

Instruções assembly mais comuns

Sex

19

Jun

2009


14:29

(22 votos, média 4.73 de 5) 


Iniciantes A linguagem Assembly a ser utilizada depende essencialmente do processador ao qual se destina, ou seja, é dependente da arquitetura da CPU. A seguir estão algumas das instruções mais utilizadas para processadores da família Intel. Para que possam ser entendidas perfeitamente, é preciso ter uma boa noção da arquitetura do microprocessador. Caso tenha dúvidas, leia antes "Arquitetura Intel".

Instrução AND

AND
Sintaxe and destino,fonte
Lógica destino <- destino AND fonte
Descrição AND realiza uma operação lógica AND bit a bit nos seus operandos e põe o resultado no destino.
Flags CF <- 0
OF <- 0
CF OF PF SF ZF (AF indefinido)

Há 5 modos diferentes de se ANDar dois números:

  1. AND dois registradores
  2. AND um registrador com uma variável
  3. AND uma variável com um registrador
  4. AND um registrador com uma constante
  5. AND uma constante com um registrador

Ou seja:

variável1 db ? variável2 dw ? and cl, dh and al, variável1 and variável2, si and dl, 0C2h and variável1, 01001011b

Observe que as constantes estão em notação hexadecimal e binária, as únicas aceitas por que são o único meio de expressar números bit a bit. É claro que a notação hexadecimal precisa ser convertida em 4 dígitos binários. AND retorna 1 quando ambos os operandos forem 1, senão retorna zero, conforme a tabela abaixo:

Operando 1 Operando 2 Resultado
1 1 1
1 0 0
0 1 0
0 0 0

Pode-se verificar se um registrador está zerado utilizando a instrução AND, como em and ecx,ecx. Caso algum bit em ecx estiver setado (valor 1), este mesmo bit estará setado no resultado e a flag zero (ZF) estará zerada (valor falso). Se não houver bits setados, o resultado também não terá bits setados e a flag zero (ZF) recebe o valor 1. Nenhum bit será alterado e ecx mantém o seu valor original. Este é o modo padrão de se checar valores zerados. Uma alternativa para este teste é usando a instrução TEST.

Também é possível testar uma variável com uma constante (fazer AND em duas variáveis dá erro!). No caso de and variável1, 11111111b testa-se todos os bits da variável1 com bits setados. Se algum bit da variável1 estiver setado, aparece setado no resultado e ZF = 0; se todos estiverem zerados, continuam zerados no resultado e ZF = 1. O valor da variável1, em ambos os casos, não é alterado.

AND também é utilizado em máscaras. Caso se queira testar o bit na posição 0 do registrador ecx, podemos utilizar a instrução and ecx, 00000001b. O estado deste bit (setado ou zerado) será transportado para o resultado enquanto todos os outros serão zerados.

Instrução CMP

CMP
Sintaxe CMP destino, fonte
Flags AF CF OF PF SF ZF
Descrição Subtrai a fonte do destino, atualiza as flags porém não armazena o resultado.

A fonte pode ser um registrador, um endereço de memória ou um valor. O destino pode ser um registrador ou um endereço de memória. Exemplos:

cmp eax, variável1 cmp variável2, TRUE

Instrução DEC

DEC
Decrementa o valor de um registrador ou de uma variável em 1.

Exemplos:

dec eax dec variável1

Instrução INC

INC
Incrementa o valor de um registrador ou de uma variável em 1.

Exemplos:

inc eax inc variável1

Instruções de salto

Apenas os principais tipos de salto (jump) estão na tabela abaixo:

Asm Hexa Descrição
ja 77 ou 0F87 salte se acima (jump if above)
jae 73 ou 0F83 salte se acima ou igual (jump if above or equal)
jb 72 ou 0F82 salte se abaixo (jump if below)
jbe 76 ou 0F86 salte se abaixo ou igual (jump if below or equal)
je 74 ou 0F84 salte se igual (jump if equal)
jg 7F ou 0F8F salte se maior (jump if greater)
jge 7D ou 0F8D salte se maior ou igual (jump if greater or equal)
jl 7C ou 0F8C salte se menor (jump if less)
jle 7E ou 0F8E salte se menor ou igual (jump if less or equal)
jmp EB ou E9 salto incondicional
jna 76 ou 0F86 salte se não acima (jump if not above)
jnae 72 ou 0F82 salte se não acima ou igual (jump if not above or equal)
jnb 73 ou 0F83 salte se não abaixo (jump if not below)
jnbe 77 ou 0F87 salte se não abaixo ou igual (jump if not below or equal)
jne 75 ou 0F85 salte se não igual (jump if not equal)
jng 7E ou 0F8E salte se não maior (jump if not greater)
jnge 7C ou 0F8C salte se não maior ou igual (jump if not greater or equal)
jnl 7D ou 0F8D salte se não menor (jump if not less)
jnle 7F ou 0F8F salte se não menor ou igual (jump if not less or equal)
jnz 75 ou 0F85 salte se não zero (jump if not sero)
jz 74 ou 0F84 salte se zero (jump if zero)

Instrução MOV

MOV
Sintaxe MOV destino, fonte
Flags nenhuma
Descrição Copia um byte ou word do operando fonte para o operando destino.

A instrução MOV transfere (MOVe) o conteúdo da fonte para o destino. Ao se executar a transferência, o conteúdo da fonte fica preservado e o conteúdo do destino é substituído pelo conteúdo da fonte.

Instruções NEG e NOT

NOT é uma operação lógica e NEG é uma operação aritmética. Ambas são descritas em conjunto para que as diferenças fiquem claras. NOT alterna o valor de cada bit individual:

1 -> 0 0 -> 1
NOT
Sintaxe NOT destino
Lógica destino <- NOT (destino)
Descrição Inverte cada bit do operando destino formando seu complemento de um. O operando pode ser um byte ou um word.
Flags nenhuma
NEG
Sintaxe NEG destino
Lógica destino <- NEG (destino)
Descrição Subtrai o destino de 0 (zero) e salva o complemento de 2 no próprio destino.
Flags AF CF OF PF SF ZF

NEG subtrai o operando destino de 0 e retorna o resultado a este mesmo destino. O efeito é um complemento de dois do operando. O operando também pode ser um byte ou um word. NEG nega o valor do registrador ou da variável numa operação COM sinal.

NEG executa (0 - número), ou seja: neg eax neg variável1

é o mesmo que (0 - EAX) e (0 - variável1) respectivamente. NEG atualiza as flags da mesma maneira que (0 - número). Se o operando for 0 (zero), a flag de carry (CF) é zerada. Em todos os outros casos, a CF é setada para 1.

Instrução OR

OR
Sintaxe or destino,fonte
Lógica destino <- destino OR fonte
Descrição OR realiza uma operação lógica OR INCLUSIVE bit a bit nos seus operandos e põe o resultado no destino. Todos os bits ativos em qualquer dos operandos estará ativo no resultado.
Flags CF OF PF SF ZF (AF indefinido)

OR retorna 0 quando ambos os operandos forem 0, senão retorna 1, conforme a tabela abaixo:

Operando 1 Operando 2 Resultado
1 1 1
1 0 1
0 1 1
0 0 0

OR é usado para ativar bits específicos. No exemplo a seguir, apenas o bit da posição 7 é ativado e os restantes não sofrem alteração:

or dl, 10000000b ; ativa o bit da posição 7 (as posições dos 8 bits são de 0 a 7, em ordem inversa)

OR também pode ser utilizado para checar se um registrador está zerado ou não porque o resultado atualiza o estado da flag de zero (ZF). Por exemplo:

or ebx, ebx ; ebx é igual a zero ? jz ...

Instrução POP

POP
Sintaxe POP destino
Descrição OR Transfere o word do topo da pilha (SS:SP) para o destino e incrementa SP em dois para apontar para o novo topo da pilha. CS não é um destino válido.
Flags nenhuma

O destino pode ser um registrador ou um endereço de memória. A pilha é uma área de memória que armazena dados temporariamente. O registrador SP (stack pointer) sempre contém o endereço da localização que corresponde ao topo da pilha. O princípio de funcionamento da pilha é "último a entrar - primeiro a sair". A pilha é utilizada principalmente pelas instruções push, pop, call e return.

Instrução PUSH

PUSH
Sintaxe PUSH fonte
PUSH valor (apenas para 80188+)
Descrição Decrementa SP pelo tamanho do operando (dois ou quatro, valores byte são estendidos por sinal) e transfere um word da fonte para o topo da pilha (SS:SP).
Flags nenhuma

A fonte pode ser um registrador, um endereço de memória ou um valor literal. A pilha é uma área de memória que armazena dados temporariamente. O registrador SP (stack pointer) sempre contém o endereço da localização que corresponde ao topo da pilha. O princípio de funcionamento da pilha é "último a entrar - primeiro a sair". A pilha é utilizada principalmente pelas instruções push, pop, call e return.

Instruções REP, REPE e REPNE

REP / REPE / REPNE
REP (repeat / repetir), REPE (repeat if equal / repetir se igual) e REPNE (repeat if not equal / repetir se não for igual) são prefixos para instruções string que forçarão a repetição das instruções de acordo com as seguintes condições:
Prefixo ECX Efeito
rep decrementa ecx repetir se ecx não for zero
repe decrementa ecx repetir se ecx não 0 e ZF = 1
repz decrementa ecx repetir se ecx não 0 e ZF = 1
repne decrementa ecx repetir se ecx não 0 e ZF = 0
repnz decrementa ecx repetir se ecx não 0 e ZF = 0

REPE e REPZ (repeat if zero / repetir se zero) têm o mesmo efeito. O mesmo acontece com REPNE e REPNZ (repeat if not zero / repetir se diferente de zero).

Instrução SCAS

SCAS
SCAS compara AL (ou AX) com o byte (ou word) apontado por ES:[DI] e incrementa (ou decrementa) DI dependendo do valor de DF, a flag de direção. O incremento ou decremento é feito de 1 em 1 para bytes e de 2 em 2 para words. OVERRIDES NÃO SÃO PERMITIDOS.

As formas permitidas são:

scasb scasw scas BYTE PTR ES:[DI] scas WORD PTR ES:[DI]

Instrução SHL

SHL
Uso SHL destino, vezes
Descrição Desloca os bits do destino para a esquerda as "vezes" indicadas com zeros colocados à direita. A flag de carry conterá o valor do último bit deslocado.
Flags CF OF

O destino pode ser um registro ou um endereço de memória. As "vezes" podem ser valores ou CL.

... 7 6 5 4 3 2 1 0 Descrição Carry
... 1 1 1 1 0 0 0 0    
... 1 1 1 0 0 0 0 0 SHL eax,1 1
... 1 1 0 0 0 0 0 0 SHR eax,2 1
... 0 0 0 0 0 0 0 0 SHR eax,2 0

Instrução SHR

SHR
Uso SHR destino, vezes
Descrição Desloca os bits do destino para a direita as "vezes" indicadas com zeros colocados à esquerda. A flag de carry conterá o valor do último bit deslocado.
Flags CF OF

O destino pode ser um registro ou um endereço de memória. As "vezes" podem ser valores ou CL.

... 7 6 5 4 3 2 1 0 Descrição Carry
... 1 1 1 1 0 0 0 0    
... 0 1 1 1 1 0 0 0 SHR eax,1 0
... 0 0 0 1 1 1 1 0 SHR eax,2 0
... 0 0 0 0 0 1 1 1 SHR eax,2 1

Instrução SUB

SUB
Sintaxe SUB destino, fonte
Lógica destino <- destino - fonte
Descrição Subtrai a fonte do destino e o resultado é armazenado no destino.
Flags AF CF OF PF SF ZF

Ambos os operandos podem ser bytes ou words e ambos também podem ser números binários com ou sem sinal.

Instrução TEST

TEST
Sintaxe TEST destino, fonte
Lógica (destino AND fonte)
Descrição TEST realiza uma operação lógica AND bit a bit nos seus operandos sem alterá-los. Apenas modifica as flags.
Flags CF <- 0
OF <- 0
CF OF PF SF ZF (AF indefinido)

Esta instrução é uma variação da instrução AND. TEST faz exatamente o mesmo que AND, apenas descarta os resultados obtidos. Não modifica o destino. Isto significa que pode checar coisas específicas sem alterar os dados. Em outras palavras, TEST faz um AND lógico em seus dois operandos e atualiza as flags sem modificar o destino e a fonte.

test ebx,ebx ; EBX é zero ? jz ... ; se sim, então salta

Para otimizar a velocidade, quando comparar um valor num registrador com 0, use o comando TEST. Use TEST quando for comparar o resultado de um comando lógico AND com uma constante imediata se o registrador utilizado for EAX. Também pode ser usado para testar se determinado valor é zero (exemplo: test ebx,ebx seta a flag zero (ZF) se EBX for zero).

TEST é muito útil para examinar o status de bits individuais. Por exemplo, o snippet abaixo passará o controle para UM_CINCO_OFF se ambos os bits 1 e 5 do registrador AL estiverem zerados (lembre-se de que os bits são numerados de 0 a 7 em ordem inversa). O status de todos os outros bits será ignorado.

test al,00100010b ; filtre os bits 1 e 5 jz UM_CINCO_OFF ; se o bit 1 ou o bit 5 estiverem setados, o resultado ; será diferente de zero ... AMBOS_NAO_OFF: ... UM_CINCO_OFF: ...

TEST oferece as mesmas possibilidades que AND:

variável1 db ? variável2 dw ? test cl, dh test al, variável1 test variável2, si test dl, 0C2h test variável1, 01001011b

Um bom exemplo é para a placa de vídeo. Em modo texto, a tela tem 80 x 25 pixels, perfazendo 2000 células. Cada célula possui um byte de caracter e um byte de atributos. O byte do caracter é o valor ASCII do mesmo. O byte de atributos indica a cor do caracter, a cor de fundo, se o caracter está em alta ou baixa intensidade ou se está piscando. Um byte de atributos tem a seguinte aparência:

7 6 5 4 3 2 1 0
X R G B I R G B

Os bits 0, 1 e 2 (RGB) indicam a cor do caracter. 2 é vermelho (Red), 1 é verde (Green) e 0 é azul (Blue). Os bits 4, 5 e 6 (RGB) contém a cor de fundo do caracter, onde 6 é vermelho (Red), 5 é verde (Green) e 4 é azul (Blue). O bit 3 indica alta intensidade e o bit 7 é piscante. Se o bit estiver setado (valor 1), o componente correspondente está ativado. Se o bit estiver zerado, o componente correspondente está desativado.

A primeira coisa que chama a atenção é o quanto de memória é economizado pelo fato das informações estarem todas juntas. Claro que seria possível usar um byte para cada uma das características, mas a memória requerida seria de 8 x 2 000 bytes = 16 000 bytes. Se adicionarmos os 2 000 bytes referentes aos caracteres, o total já seria 18 000 bytes. Da forma explicada acima, obtém-se o mesmo resultado com apenas 4 000 bytes, ou seja, uma economia de 75%. Como há quatro telas (páginas) diferentes numa placa com cores, os totais seriam 72 000 (18 000 x 4) contra 16 000 (4 000 x 4).

Imagine agora que um dos bytes de atributos esteja no registrador DL - pode-se achar quais os bits que estão setados, bastando para isto fazer um TEST DL com um padrão de bits específico. Se a flag zero (ZF) for setada, significa que o resultado é zero e que o bit estava zerado.

test dl, 10000000b ; está piscando ? test dl, 00010000b ; tem azul no fundo ? test dl, 00000100b ; a cor do caracter é vermelho ?

A flag zero (ZF) indica se o componente está ativo ou desativo. Esta flag não vai mostrar se a cor de fundo é azul, porque o vermelho e o verde do fundo também podem estar setados. Apenas um dos componentes pode ser testado em cada test. E lembre-se: TEST não altera os valores da fonte ou do destino, apenas atualiza as flags.

Máscaras

Usaremos o byte de atributos do monitor para exemplificar o uso de máscaras.

7 6 5 4 3 2 1 0
X R G B I R G B

Os bits 0, 1 e 2 (RGB) indicam a cor do caracter. 2 é vermelho (Red), 1 é verde (Green) e 0 é azul (Blue). Os bits 4, 5 e 6 (RGB) contém a cor de fundo do caracter, onde 6 é vermelho (Red), 5 é verde (Green) e 4 é azul (Blue). O bit 3 indica alta intensidade e o bit 7 é piscante. Se o bit estiver setado (valor 1), o componente correspondente está ativado. Se o bit estiver zerado, o componente correspondente está desativado.

Caso se queira ativar ou desativar determinados bits, sem alterar o valor dos outros, podemos lançar mão de uma máscara AND: and byte_do_video, 10001111b. Lembrando que a instrução AND retorna 1 apenas quando ambos os bits estiverem setados (tiverem valor 1), sabemos que neste caso os bits 4, 5 e 6 serão zerados enquanto que os outros permanecem inalterados. Como os bits zerados correspondem à cor de fundo, esta operação tornou a cor de fundo preta.

Se quisermos definir a cor de fundo, precisamos de duas operações. A primeira, uma operação de máscara AND como descrito acima, para fazer a cor de fundo preta zerando os bits desejados sem modificar os restantes. A segunda, uma operação de máscara OR, para ativar os bits desejados sem alterar os restantes (cor de fundo azul):

and byte_de_video, 10001111b
or byte_de_video, 00010000b

As constantes binárias utilizadas para fazer o AND e o OR são chamadas de máscaras. Estas constantes podem estar no formato binário ou hexadecimal. Por exemplo, and byte_de_video, 10001111b é o mesmo que and byte_de_video, 8Fh e or byte_de_video, 00010000b é o mesmo que or byte_de_vídeo, 10h.

Reveja as instruções AND e OR caso ainda tenha alguma dúvida.

Instrução XOR

XOR
Sintaxe XOR destino, fonte
Lógica destino <- destino XOR fonte
Descrição XOR realiza uma operação lógica OR EXCLUSIVE bit a bit nos seus operandos e põe o resultado no destino.
Flags CF OF PF SF ZF (AF indefinido)

XOR retorna 1 quando os operandos forem diferentes, senão retorna 0, conforme a tabela abaixo:

Operando 1 Operando 2 Resultado
1 1 0
1 0 1
0 1 1
0 0 0
  Decimal Binário
  77 01001101
XOR 25 00011001
Resultado 84 01010100

O OU-Exclusivo Lógico (XOR) significa que o resultado SÓ É VERDADEIRO SE AS CONDIÇÕES FOREM DIFERENTES. Falso e verdadeiro também podem indicar o estado de bits, portanto, podemos efetuar uma operação de OU-Exclusivo Lógico entre dois bits (como na tabela acima) ou numa sequência de bits. Tomemos como exemplo a operação 77 XOR 25. Como sabemos que a operação lógica XOR também é feita bit a bit, precisamos dos valores binários desses dois números para efetuar a operação:

Observe que apenas nas posições onde os bits são diferentes o resultado possui bits com valor 1, portanto, 77 XOR 25 = 84. Um aspecto interessante da operação XOR é que ela é reversível: se fizermos um XOR do resultado com o primeiro operando, obtemos o valor do segundo operando. Da mesma forma, se fizermos um XOR do resultado com o segundo operando, o resultado é o primeiro operando. Outra característica é que, fazendo o XOR de um número com ele mesmo, o resultado sempre será zero. Faça os testes e verifique wink





mfxbroker.combobbi brown кисти для макияжаполигон ооохарьков лобановскийлобановский александр интервьюtrans siberian railway ticketлобановский класс

Informações adicionais