Caminhando em direção à linguagem propriamente dita, precisamos saber que existem duas principais sintaxes de Assembly, que são diferentes uma da outra. A Intel, utilizada principalmente em sistemas Windows, e a AT&T, utilizada em sistemas
GNU/Linux.
E há diferenças bem importantes entre estas sintaxes. Diz-se que dificilmente alguém aprende a sintaxe AT&T primeiro, pois ela pode ser um pouco confusa para iniciantes. Mas depois que se aprende, torna-se uma poderosa ferramenta. Eu, pelo menos, sou adepto da sintaxe AT&T e é essa que vamos abordar neste artigo.
Por exemplo, na sintaxe Intel, uma instrução comum ficaria assim:
instrução destino, origem
Em AT&T é:
instrução origem, destino
Na sintaxe AT∓T, quando desejamos realizar algum tipo de endereçamento de memória, precisamos seguir a seguinte sintaxe de comando:
segmento:offset(base, indexador, escala)
Na Intel, um endereçamento ficaria assim:
[es:eax+ebx*4+100]
Já na AT∓T, a mesma linha ficaria assim:
%es:100(%eax, %ebx, 2)
Uma questão importante de se lembrar, é que na sintaxe AT∓T, todos os registradores devem ser prefixados pelo símbolo %, enquanto que o valores literais, pelo
símbolo $. Portanto, 100 é diferente de $100, onde o primeiro é um endereço de memória, e o segundo é um valor numeral.
Outro símbolo importante, é o '$0x' utilizado para referenciar hexadecimais.
Vamos deixar a teoria um pouco de lado e vamos ao nosso primeiro programa. Ele fará pouca coisa por enquanto, apenas executará um 'exit', utilizando uma 'syscall' específica do sistema operacional GNU/Linux. Vejamos o código, que pode ser digitado utilizando o Vim/Vi, Nano, Emacs ou seja lá o que preferir:
#OBJETIVO: Programa simples que executa um exit e retorna um código de status para o kernel Linux
#
#ENTRADA: nenhuma
#
#OUTPUT: retorna um status código de status, que pode ser visto executando no terminal o comando:
#
# echo $?
#
# após a execução do programa
#
#VARIÁVEIS:
# %eax armazena o número da syscall
# %ebx armazena o status retornado
#
.section .data
.section .text
.globl _start
_start:
movl $1, %eax # esta é a syscall do kernel Linux para sair de um programa
movl $0, %ebx # este é o status que retornaremos para o SO.
# altere esse valor, e verá coisas diferentes ao executar o
# echo $?
int $0x80 # isso chama o kernel para executar a syscall 1
Salve este código como 'exemplo1.s', compile e linkedite-o:
# as exemplo1.s -o exemplo1.o
# ld exemplo1.o -o exemplo1
Após este processo, para executar nosso primeiro programa, basta digitar no terminal:
# ./exemplo1
Executando o programa, você perceberá que a única coisa diferente que ocorrerá, é que seu cursor irá para a próxima linha. Isto ocorre porque nosso programa foi feito apenas para executar um 'exit'.
Para visualizarmos o código de status retornado para o SO, basta digitarmos no terminal:
# echo $?
Se tudo correr bem, você terá um "0" como saída. Este é o código de status necessário a ser passado para o kernel, avisando de que tudo está ok para sair do programa.