O assembler 80386
possui uma grande variedade de instruções que podem ser utilizadas
pelo programador. No entanto, a prática tem demonstrado que
bastam umas cinqüenta para resolvermos quase todos os problemas
que aparecem na criação de um programa. Então, vamos nos concentrar
nelas.
MOV - tudo,
em assembler, sempre está indo de um lugar para outro. Os dados
são na verdade valores numéricos que manipulamos de uma ou de
outra forma. A instrução mov permite deslocar
valores entre endereços de memória ou entre registradores.
Veja os exemplos:
mov eax,1995
Faz com que o valor numérico 1995
seja colocado no registrador EAX. Seria o mesmo
que dizer EAX:= 1995.
mov ebx,eax
Faz com que o registrador EBX
passe a ter o mesmo valor que EAX. Poderia
ser compreendido como EBX:= EAX.
mov eax,[1995]
Faz com que EAX
contenha o valor que está no endereço 1995.
mov eax,[ebx]
Faz com que EAX
contenha o valor que está no endereço apontado pelo registrador
EBX.
Note, por esses
exemplos, que a instrução mov possui sempre
dois parâmetros e que o movimento é sempre no sentido do segundo
para o primeiro, ou seja, é o primeiro parâmetro que é alterado.
Essa regra vale também para as outras instruções com dois parâmetros.
CALL -
chama uma subrotina. Pedaços repetitivos de programas podem
ser transformados em subrotinas e chamados de qualquer parte
do programa principal. O endereço da próxima instrução é salvo
no topo da pilha do stack para ser usado como endereço de retorno,
ou seja, no final da subrotina o programa volta ao ponto de
chamada.
Essa é uma das
principais ferramentas de programação assembler. Por exemplo:
cria-se uma rotina para colocar uma letra na tela. Sempre que
se deseja mostrar alguma palavra ou frase, podemos usar a rotina
de impressão de letras repetitivamente.
call 1993
;chama a rotina no endereço 1993
call ebx ;chama a rotina no endereço apontado por ebx
call [ebx] ;chama a rotina no endereço conteúdo ebx
RET -
retira um endereço do topo da pilha do stack e desvia o processamento
para ele. É a instrução que faz "voltar" da subrotina que foi
chamada pelo programa principal.
ret
PUSH -
coloca uma palavra (dword) no topo da pilha do stack. A pilha
é manipulada sempre do endereço mais alto para o mais baixo.
O ponteiro do stack ESP aponta sempre para
o último dado inserido na pilha. Esse stack, chamado de stack
do processador, é uma área de armazenamento temporário de dados.
push eax
Coloca no stack o valor contido
em EAX. Esta operação não altera o conteúdo
de EAX.
POP -
retira uma palavra do topo da pilha do stack. É o contrário
de push, ou seja, serve para pegar de volta
um valor.
pop eax
ADD
- soma dois operandos e coloca o resultado no
primeiro operando. É a velha operação de soma.
add eax,32000
Soma o valor 32 mil ao registrador
EAX. Como a capacidade desse registrador é
de 32 bits, o valor máximo da soma terá que ser 4.294.967.295.
Se passar disso, o carry flag é setado (1) avisando que ocorreu
overflow e o valor restante é colocado em EAX.
SUB
- subtrai dois operandos e coloca o resultado
no primeiro operando. É a subtração, que segue a mesma regra
da adição.
sub eax,50000
sub eax,[ebx]
CMP
- compara dois operandos e sinaliza o resultado
da comparação através dos flags. Uma comparação é na verdade
uma subtração onde o primeiro operando é subtraído do segundo
operando, mas sem que ambos sejam alterados.
cmp eax,50000
cmp eax,[ebx]
INC
- incrementa de uma unidade o operando. É o
popular "mais um".
inc ebx
inc [esi]
DEC
- decrementa de uma unidade o operando. É o
popular "menos um".
dec ebx
dec [esi]
JMP
- salta para o endereço dado no operando. Passa
a executar o programa a partir deste novo endereço.
jmp 1995
;Salta para o endereço 1995
jmp ebx ;Salta para o endereço em ebx
jmp [ebx] ;Salta para o endereço que está no endereço
;apontado por ebx
Saltos condicionais: são saltos
efetuados sempre que uma condição esteja presente. Os principais
são:
JNC - salta
se o carry flag for 0
JC - salta se o carry flag for 1
JNZ - salta se o zero flag for 0
JZ - salta se o zero flag for 1
LOOP
- decrementa o registrador ECX
e produz um salto para o operando, caso o valor em ECX
ainda não seja zero. Esta instrução é usada em operações repetitivas.
loop 1993
NOP
- não produz nenhum tipo de resultado. Esta
instrução é usada apenas quando se deseja "perder" tempo de
processamento, ou preencher áreas de memória com código nulo.