26.10.01

                                    ____
                          __      _|___ \__  __
                          \ \ /\ / / __) \ \/ /
                           \ V  V / / __/ >  <
                            \_/\_/ |_____/_/\_\

                            - Write To Execute -
                     http://www.write2execute.cjb.net/



Desenvolvido por Gustavo Chagas a.k.a Rofeti
hophet@yahoo.com.br

Este e outros txts podem ser obtidos em:
http://www.write2execute.cjb.net/
http://www.bthzine.cjb.net/


Tanks Unsekurity Scene
http://www.unsekurity.com.br/




                   #####################################
                   ##### Manual basico de Assembly #####
                   ####### em Linux/i386 - AT&T ########
                   #####################################



* Indice

$0x1 - Introducao.
$0x2 - Introducao ao Assembly.
$0x3 - Modelo de Memoria.
$0x4 - O Stack.
$0x5 - Registradores.
$0x6 - Instrucoes.
$0x7 - Secoes.
$0x8 - System Calls.
$0x9 - Exemplos.
$0xa - Links.
$0xb - Terminando.




------------------
$0x1 - Introducao |
------------------

Ae irmaos, estive um tempo sumido, tive uns problemas com a minha
linha telefonica:/, mas ja esta tudo resolvido, e a luta continua
:). Trago mais uma vez a voces minhas humildes palavras, com o 
intuito de mostrarlhes um pouco mais sobre esta facinante linguagem
que eh o Assembly. O mundo hoje esta vivendo um grande rebulico,
nacoes inteiras preocupadas com a sua seguranca, os especialistas
dizem que mesmo as mais drasticas medidas de seguranca nao vao 
resolver os problemas e que nada esta seguro hoje em dia. Serah o
fim do mundo?? hehehe talvez:). Nos resta esperar com uma certeza
no coracao, de que Deus irah voltar e se voce nao estiver preparado,
nao irah subir com ele:). Voltando ao assunto, este tutorial esta 
direcionado a Newbies fucadores que querem entender um poukinho mais 
do Assembly em linux/x86, vamos direcionar os nossos esforcos na 
sinteze AT&T, se voce estiver interecado em ASM na sinteze INTEL,
procure algo nos links no final deste txt. Soh pra esclerecer 
assembly eh a linguagem e Assembler eh o compilador ASM.

Quero dizer ao pessoal que o "w2x" estah vivendo um novo momento,
que eh a procura de melhorar mais, e que estao vindo por ae gran_
des coisas realizadas pelo w2x, partindo por boms materiais como
este.  



------------------------------
$0x2 - Introducao ao Assembly |
------------------------------

Eh, usaremos em todo o txt a sinteze AT&T, todos os exemplos sao 
para linux/x86, usaremos o "as" para criarmos o object file e o
linker "ld" para linkarmos o object file assim criando o executavel 
Com o ASM no linux, trabalharemos com 32bit's em "Protect Mode",
Modelo de Memoria Flat, e com binarios ELF. Um programa Assembly eh 
dividido em secoes depois de compilado e antes tambem, depois de
compilado ele tem 3 secoes, a ".text" para o codigo(Read-Only), a 
".data" para os dados(Read-Write) e a ".bss" para inicializacao de
dados(Read-Write), vou falar mais neles nas proximas secoes. 
Como muitos ja sabem com o Assembly se tem um poder total do sistema, 
podendo se manipular desde registradores do processador ate a 
memoria. Asm possibilita a criacao de programas bem menores e mais 
rapidos que os feitos em outras linguagens, pois sao feitos usando-
se diretamente a memoria e os system calls, por isso um controle
total do sistema. 
Assembly permite que voce desenvolva suas proprias rotinas, usando
diretamente a memoria e chamadas de sistema, o que te possibilita
um poder muito grande. 


* Alguma informacoes uteis
--------------------------


Sinteze AT&T:
-------------

Na sinteze AT&T o "origem" vem 1o que o "destino", um exemplo disso 
seria "addl origem,destino".
Outro ponto importante eh que os registradores recebem o sinal de 
porcentagem "%", assim os registradores no AT&T sao: %eax, %ebx, 
%ecx, %edx, %esi, %edi, %esp, %ebp...
Os operandos recebem o sinal "$", assim "addl $3, %eax" que adiciona
3 ao %eax, se o "$" for omitido, ele serah tratado como um endereco 
de memoria. Assim, "addl 3, %eax", o 3 serah tratado como um endereco
de memoria, adicionando o endereco ao %eax e "addl $3, %eax" serah 
tratado como um openrando 3, ou variavel. 
O "e" antes dos registradores indica que ele eh "extendido"(32bits).
ex.: %ecx.

Unidades de medida:
-------------------

Eu aconselho ao pessoal interecado, a ler uma materia na edicao 00
da zine bth, sobre "conversao numerica" importante p/ um entendimento
maior deste txt, voce pode pega-la em "http://www.bthzine.cjb.net".

Soh para esclerecimento rapido:

1 bit = 0 ou 1
1 byte = 8 bits
1 kbyte = 1024 bytes
1 mbyte = 1024 kbytes
1 gbyte = 1024 mbytes
1 tbyte = 1024 gbytes

1 Nibble = 4 bits, valor maximo de 15.
1 Word = 16 bits ou 2 bytes, Eh o tamanho dos registradores 80x86.
1 DWord = 32 bits ou 4 bytes, Eh o tamanho dos registradores 
          linux/i386.


Compilando codigos ASM:
-----------------------

Para compilarmos programas Assembly usaremos "as" e "ld" como disse
um pouco antes... basicamente seria:

Criaremos o Object File...
$ as -o codigo.o codigo.s

E linkaremos...
$ ld -o codigo codigo.o

Pronto temos o nosso executavel final...
$ ./codigo 

Mas vamos um pouco alem para criarmos um programa ainda menor,  
do que temos. 


Copie e compile este pequeno codigo para que possamos fazer os
nossos testes de compilacao...

<++> asm/big.s

#
# Programa teste de compilacao do txt de Assembly
# 

.section .data

OI: .string "OI!!!\n" 
TAM: .long . - OI

.section .text

.globl _start

_start:

      movl $0x4, %eax
      movl $0x1, %ebx
      movl $OI, %ecx
      movl TAM, %edx  
      int $0x80 
 
      movl $0x1, %eax
      movl $0x0, %ebx
      int $0x80

# eof

<-->

Compilado, vamos ver o seu tamanho...

$ wc -c big
    754 big

Vemos que ele tem 754 bytes, vamos tentar diminuir este tamanho,
ainda mais. Veja:

$ as -o big.o -S0
$ ld -s -O0 -o big big.o

Com a opcao "-s" nos tiramos as informacoes dos simbolos do binario
final com isso ele diminui bastante o seu tamanho.

$ wc -c big
    404 big

Vemos que agora ele tem 404 bytes.

Uma ferramenta muito boa para mais informacoes sobre o binario
e ate um entendimento maior de como um progrma eh dividido eh o
"objdump" que mostra boas informacoes... Tente aih um:

$ objdump -x big

Para mais informacoes "man objdump".


Comentarios em Assembly:
------------------------

Os comentarios em ASM variam de tipo, de acordo que muda o 
tipo de programacao em ASM, o comentario usado por nos neste 
txt, usando o assembler as e o ld no AT&T eh o sinal de cer_
quinha(#), assim "# isto eh um comentario" pra nos eh o nosso
comentario. Pro pessoal da sinteze Intel, seria usado o sinal
ponto e virgula, assim "; isto eh um comentario" pra eles eh
um comentario, mas nos no atentaremos para o cerquinha "#". 
Ex.:

# 
# Muito obrigado por ler este COMENTARIO :D
# !! w2x - vive em nossos coracoes - w2x !!
#


Os perenteses:
--------------

Os parenteses "()" sao os "Operandos de Memoria" do Assembly
na sinteze AT&T, a base do registrador eh envoldida em "("
e ")". Eles sao responsaveis por facilitar operacoes
envolvendo registradores e enderecos de memoria.  Ex.:

leal 4(%eax), %ebx 
movl (%eax, %ebx, $0x4), %esp
movl (%ebx), %eax



-------------------------
$0x3 - Modelo de Memoria |
-------------------------

Como ja foi dito antes um linux/i386 possui o modelo flat de 
32bit's, onde os registradores, vao de 8 a 32bit's. Um programa 
pode ser dividido em tres partes ou secoes como preferir. Sao
elas:


.data (Stack) => para seus dados, variaveis, etc. Read-Write.

.bss (Heap) => para dados indefinidos, inicializacao de dados. 
               Read-Write.

.text => para seu codigo. Read-Only.

Um programa ASM tem que ter no minimo a secao ".text". Um programa
em "C" possue varias secoes alem dessas. 


Segmentos de Memoria: eh todo o local na memoria alocada pelo 
programa.

offset(deslocamento): eh um local(parte) do espaco na memoria 
alocada pelo programa.

Ex.: 

  1  2  3  4   -> offset's
 -------------
 |A-|B-|C-|D-| -> 100
 ------------- 
 I___________I
       I
    Segmento   


Por exemplo o "A" se encontra no segmento "100" e no offset "1",
e o "D" se encontra no segmento "100" e no offset "4". Mas em 
vez de numeros decimais como acima, sao usados numeros hexa_
decimais ou ate binarios. 

A memoria de todos os PC's eh dividida em "segmentos", cada 
segmento possui 64kbytes, e eles sao separados por 16bits, ou
seja, o 1o segmento eh distante 16bits do 2o segmento. Aih 
entra o offset, se quizesemos localizar o "vigesimo(20)" byte 
do segmento "0", teriamos "0:20", ou seja, segmento 0 offset 20,
lembrando que seria tudo em hexadecimal (Aconselho a leitura da
materia indicada na secao "Unidades de Medida"), mais ou menos
assim "0x0:0x14", soh que seriam enderecos de memoria mesmo, 
pelo menos no segmento.



---------------
$0x4 - O Stack |
---------------   


O Stack funciona de acordo com o sistema LIFO(Ultimo a entrar,
primeiro a sair). Regiao responsavel por receber dados e passa_
los as funcoes, ou a quem os requisitar. Conhecido como Stack ou
Pilha, pelo fato de funcionar realmente como uma, ou seja, o ulti_
mo a entrar na "pilha" vai ser o primeiro a sair da "pilha". Usa_
mos o "push" para colocarmos dados no Stack e o "pop" para tirarmos
dados do Stack, os mesmos serao descritos mais abaixo. Repare este
exemplo:
                                   
       push $0x2e # .          
       push $0x54 # T       
       push $0x45 # E
       push $0x48 # H  
       push $0x50 # P
       push $0x4f # O
       push $0x48 # H    Stack = HOPHET

       pop %esp   # clear stack.  Stack = 0

Se usasemos a syscall write para escrever na tela o Stack Pointer
teriamos 1o o "H" depois o "O" e assim por diante ate completar o
"HOPHET". A pilha ou Stack, serve para se armazenar dados que 
poderao ser recuperados sem que tenhamos que usar um dos regis_
tradores para este fim, ela eh tambem usada para armazenar o ende_
reco de retorno de sub-rotinas. 



---------------------
$0x5 - Registradores |
---------------------

Os registradores sao como lugares onde se recebem e guardam 
dados, variaveis, eh muito usado no assembly. Eles na maioria
recebem dados para que depois sejam enviados a memoria ou ate
outro registrador. Cada um contem 16bit's e pode ser dividido
em duas partes de 8bit's, a parte baixa(low) com os primeiros
8bit's e a parte alta(high) com os ultimos 8bit's. Eles podem
receber 1byte(8bits) ou 2bytes(16bits), como vamos ver regis_
tradores espandidos de 32bits, eles vao ser divididos em duas
partes de 16bit's podendo receber ate 1word(32bits) ou 4bytes
no total e 2bytes cada parte, mas nos neste txt usaremos some_
nte o registrador no seu total, ou seja, usaremos os 32bit's
e deicharemos o programa decidir onde sera melhor ele guardar 
os dados, por isso os registradores estarao sempre com seus 
nomes no total e usando os 32bit's por exemplo "%eax". 
Soh lembrando, os registradores na sinteze AT&T e no linux/i386 
como espandido recebem o sinal de porcentagem(%) e um "e" antes 
para definilos como espandido, ficando desta forma "%eax". 
Soh pra exclarecer o porque dos registradores agora serem de 
32bit's, antes na era 8086 os barramentos eram de 16bits por
isso os registradores tinham os seus 16bits, depois com a che_
gado dos 386, 486 em diante, que tinham barramentos de 32bit's,
e consequentimente registradores de 32bit's, houve esta mudanca
na programacao ASM em 386 em diante, mas nao muda muita coisa,
a maior eh o tamanho. 
   
Vamos a eles: 


Registradores Gerais:
---------------------

* EAX: Conhecido como Registrador Acumulador, possui 32bit's,    
       podemos acessar uma parte apenas se quizesemos, tendo
       apenas que declaralo como %AL ou %AH. %AL para acesar_
       mos a parte baixa e %AH para acesarmos a parte Alta. 
       Este registrador eh bastante usado nas operacoes de I/O
       (Entrada e Saida) de dados, ele acumula dados. Ex.:

       leal FRASE, %eax # Move o conteudo da variavel FRASE 
                        # para o registrador %EAX.


* EBX: Conhecido como Registrador Base. Ele como todos os outros
       possui o %BL e o %BH. Bastante usado como um registrador 
       de offset. Ex.:
         
       movl $0x1, %ebx # Move 1 para o %EBX.


* ECX: Conhecido como Registrador Contador(Count). Ele tem o 
       %CL e o %CH. Este registrador eh bastante usado em si_
       tuacoes de contagem, Loop e desvios condicionais. Ex.:
        
       movl $FRASE, %ecx # Move o conteudo da variavel FRASE
                         # para o registrador %ECX.


* EDX: Conhecido como Registrador de Dados, bastante usado para
       receber(guardar) dados. %DL parte baixa e %DH parte alta.
       Bastante usado em operacoes aritmeticas, como "add","sub",
       etc. Ex.:

       add $0x14, %edx # Adiciona ou Soma "20" ao registrador 
                       # %EDX. 


* ESI: Conhecido como Registrador Indice Fonte(Source Index), muito
       usado para movimentacao de blocos de instrucoes, ele aponta
       para a proxima instrucao. Ex.: 

       addl $0x1, %esi # Adiciona 1 ao bloco de instrucoes definidas
                       # anteriormente em %ESI.


* EDI: Conhecido como Registrador Indice Destino(Index Destination),
       ele pode ser usado como um registrador de offset's, bastante
       usado em operacoes com movs e stos. Ex.:

       movsb %edi # Move 1byte para o registrador %EDI.


* EIP: Conhecido como Registrador Apontador de Instrucao(Instruction
       Pointer), ele eh o offset do segmento de codigo que contem a 
       proxima instrucao a ser executada. Este registrador nao eh 
       acessivel por qualquer instrucao. 


Existem outros mais gerais, o EIP(Instrucion Pointer) os FS e GS
que sao para Segemento de Dados. Os registradores CS, DS, ES, SS, 
nao mudaram de tamanho e ainda possuem o tamanho de 16bit's. Existe 
ate um registrador FLAGS(sinalizadores) e o de 32bit's EFLAGS, que 
eh responsavel por mudar opcoes ou parametros(sinais) dentro do 
processador para os outros registradores.


Registradores de Segmento:
--------------------------

* CS: Conhecido como Registrador Segmento de Codigo(Code Segment).
      Refere-se a parte na memoria(bloco) onde os codigos sao arma_  
      zenados, ele aponta para a proxima instrucao, e nao pode ser
      mudado diretamente, mas pode ser usado como "origem". Ex.:
    
      movl %cs, %eax # Move o Conteudo de %CS para %EAX


* DS: Conhecido como Registrador Segmento de Dados(Data Segment),
      Representa a area na memoria onde os dados sao armazenados,
      todos os dados lidos pela CPU sao do segmento apontado para
      este registrador, ou seja, os dados antes passao por ele. 
      Usado como segmento(endereco) origem para operacoes com mov,  
      lods. Eh o Segmento de Dados Default. Tambem nao pode ser 
      mudado diretamente, mas pode ser usado como "origem". Ex.:

      movl %ds, %ebx # Move o Conteudo de %DS para %EBX

* ES: Conhecido como Registrador Segmento Extra(Extra Segment), 
      usado como o segmento de destino em operacoes de transfe_
      rencia e movimentacao de dados como mov. Nao pode ser mu_
      dado diretamente, mas pode ser usado como "origem". Ex.:

      movl %es, %ecx # Move o Conteudo de %ES para %ECX


* SS: Conhecido como Registrador Segmento de Pilha(Stack Segment),
      ele eh usado pela CPU para armazenar enderecos de retorno de
      sub-rotinas, eh o segmento onde reside o "Stack". Ele nao 
      pode ser mudado diretamente, mas pode ser usado como "origem".
      Ex.:

      movl %ss, %edx # Move o Conteudo de %SS para %EDX 


Registradores de Indexacao de Stack:
------------------------------------

* EBP: Conhecido como Registrador Apontador Base(Base Pointer),
       ele eh usado para se acessar o Stack. Ele pode ser usado
       como apontador para a base da pilha(ja que por default 
       esta relacionado com o SS) ou ate como um registrador 
       comun. Ex.:
   
       movl %ebp, %edi # Move o %EBP para o %ESI.


* ESP: Conhecido como Registrador Apontador do Stack(Stack Pointer),
       ele aponta para a posicao de memoria atual do Stack. Sao usa_
       dos para se manipular dados. Este registrador eh o offset do
       segmento SS(Segmento de Pilha) onde o proximo dado vai ser 
       empilhado. Ex.:

       pop %esp # Retiramos todos os dados do %ESP, como um 
                # Clear Stack:).
       subl $0x0a, %esp # Subtrai(Tira) 10bytes do Stack,
                        # reserva espaco.


   

------------------
$0x6 - Instrucoes |
------------------

As Instrucoes sao usadas para realizarem uma determinada acao,
elas sao as responsaveis por movimentarem dados na memoria,
registradores,etc , elas fazem a maior parte do trabalho,se 
nao todo o trabalho de transferencia de dados, testes logicos,
comparacao,etc. 


Instrucoes de Movimentacao: 
--------------------------- 

Sao as instrucoes responsaveis por transferir dados de registra_
dores ou memoria para outras regioes na memoria, ou outros regi_
stradores. Vamos a elas:

* MOV: Esta instrucao move dados entre registradores e memoria,
       sua sinteze eh "mov origem,destino", onde origem pode ser
       um registrador, memoria ou um operando qualquer. Ele basi_
       camente Movimenta dados de um lugar para o outro. Ex.:

       mov $0x4, %eax # Move "4" para o registrador %EAX

       Existem algumas variantes do MOV, elas tambem movimentao
       dados de uma posicao na memoria para outra diretamente.
       Sao elas:

       MOVL: Esta Instrucao move dados para a parte baixa dos 
             registradores. Ex.:

             movl $0x1, %eax # eh  igual a "mov $0x1, %al"
                             # Ambos movem "1" para a parte baixa
                             # do registrador %EAX.  

       MOVSB: Esta Instrucao move 1byte. 

       MOVSW: Esta Instrucao move 1word(16bits).

       
* LEA: Bem parecido com o "mov" soh que o "lea" em alguns casos 
       executa algumas operacoes antes de mover os dados, sao cal_
       culos de endereco de memoria, como "add",etc. Mas pode ser
       usado tambem da mesma forma que o "mov", a sinteze como em
       todas as intrucoes no AT&T eh "lea origem,destino", na ins_
       trucao "lea" nao se usa o simbolo de porcentagem no "origem",
       isto porque o "origem" eh um endereco(offset), o lea calcula
       este endereco e transfere para o "destino".
       Ex.: 
 
       lea 4(%eax), %ebx # Antes de mover %EAX para o %EBX, ele 
                         # adiciona "4" ao registrador %EAX. 
                         # Sem o "lea" ficaria assim:
                         # add $0x4, %eax -> adiciona "4" ao %EAX
                         # mov %eax, %ebx -> move %EAX para o %EBX. 

       Ele como uma simples instrucao "mov" ficaria assim:

       lea 0x4, %eax

       Existem algumas variantes do "lea" sao elas:

       LEAL: Esta instrucao move dados para a parte baixa dos re_
             gistradores. Ex.:

             leal 0x4, %eax # eh igual a "lea 0x4, %al" 
                            # Ambos movem "4" para a parte baixa do
                            # registrador %EAX.

       LDS: Usado para carregar um par de registradores (segmento:
            offset) de uma soh vez. Se quizesemos carregar DS:EDX.

       LES: Usado para carregar um par de registradores (segmento:
            offset) de uma soh vez. Se quizesemos carregar ES:EDX.
            O par ES:DX, sera carregado com um Dword armazenado no
            endereco apontado por DS:SI.  


* LODSB e LODSW: Essas Instrucoes servem para ler um valor que estao
                 no endereco apontado por DS:ESI e armazenalo em EAX.
                 LODSB para 1byte e LODSW para 1word. Depois da exe_
                 cucao da instrucao o registrador ESI serah incremen_
                 tado ou decrementado para que o DS:ESI, aponte para 
                 o proximo byte ou word.


* STOSB e STOSW: Essas Instrucoes servem para armazenar um valor que
                 esta em EAX no endereco apontado por ES:EDI. STOSB
                 para 1byte e STOSW para 1word. Assim que executada
                 estas instrucoes o registrador EDI vai ser incremen_
                 tado ou decrementado assim ES:EDI vai apontar para 
                 o proximo byte ou word.


* XCHG: Esta Instrucao eh usada para trocarmos o conteudo de um regis_
        trador pelo outro. Ex.:

        movl $0x0, %eax # Move "0" para o registrador %EAX. EAX = 0 
        movl $0x1, %ebx # Move "1" para o registrador %EBX. EBX = 1
        
        xchg %eax, %ebx # Agora com os conteudos trocados,
                        # %EAX = 1 e %EBX = 0 
        

Estas Instrucao abaixo sao usadas para movimentacao/transferencia 
de dados sobre o "Stack(Pilha)", ja comentado um pouco acima.

* PUSH: Esta Instrucao eh usada para empurrar dados sobre o Stack,
        ela adiciona, coloca, empurra dados pra dentro da Pilha
        (Stack), estes dados podem ser acessados pelo registrador
        "%esp". Pode ser empurrado para o Stack enderecos de memo_
        ria, funcoes, sub-rotinas, operandos, etc Ex.:

        movl $0xa, %eax # Move "10" para o registrador %EAX.
        
        push %eax # Empurra/coloca sobre o Stack os dados contidos
                  # no registrador %EAX.   

     
* POP: Esta Instrucao eh usada para se tirar dados do Stack, ela
       faz o contrario de "push", ou seja, tira dados do Stack,
       seguindo o esquema LIFO(last in, first out). O "pop" sem_
       pre irah tirar o ultimo dado inserido no stack. Ex.:

       movl $0xa, %eax # Move "10" para o registrador %ESI
       push %eax       # Coloca os dados de %EAX no Stack.

       pop %eax        # Tira os dados colocados pelo "push"
                       # anteriormente do Stack, agora os dados
                       # contidos no %EAX que estavam no Stack
                       # nao estao mas.   



Instrucoes Aritmeticas:
-----------------------

Sao as Instrucoes utilizadas para a realizacao de calculos nos 
operadores, registradores ou memoria. Sao elas: 

* ADD: Esta Instrucao eh responsavel por fazer a "adicao" de 2
       operadores, ela adiciona dois operadores e guarda o resu_
       ltado no operador "destino". Sua sinteze eh "add origem,
       destino". O "origem" pode ser uma regiao na memoria ou 
       um operando qualquer. Ex.:

       add $0xb, %eax # Adiciona/Soma "11" ao registrador %EAX
                      # e guarda o resultado no proprio %EAX.

       Existe ainda uma variante:
      
       ADDL: Esta Instrucao adiciona/Soma dados na parte baixa 
             dos registradores. Ex.:

       addl $0xb, %eax # Soma "11" na parte baixa do registrador
                       # %EAX, eh igual a "add $0xb, %al".       


* SUB: Esta eh a Instrucao responsavel por fazer a "subtracao"
       de operadores, ela eh bastante usada para se alocar es_
       pacos no Stack para se receber dados posteriormente. Ex.:

       sub $0xa, %esp # Subtrai "10" bytes do %ESP(Stack 
                      # Pointer), para receber dados.

       Temos a variante:
       
       SUBL: Esta Instrucao Subtrai dados na parte baixa dos
             registradores. Ex.:

       subl $0xa, %edx # Subtrai "10" da parte baixa do regis_
                       # trador %EDX, eh igual a "sub $0xa, %dl".


* MUL: Esta Instrucao faz a multiplicacao de dois operadores,
       ela realiza o calculo e guarda o resultado no registra_
       dor "destino". Ex.:

       mul $0x2, %eax # Faz a multiplicacao do registrador %EAX
                      # por "2". 

       Temos a Instrucao IMUL que considera o sinal do operador,
       lembrando que o sinal de um numero inteiro depende do seu
       bit mais significativo.


* DIV: Esta Instrucao eh usada para se fazer a "divisao" de dois
       operadores, ela como as demais realiza os calculos e gua_
       rda o resultado no operador "destino". Ex.:

       div $0x2, %ebx # Faz a divisao do registrador %EBX por "2".

       Temos a Instrucao IDIV que considera o sinal do operador.


* INC: Esta Instrucao Incrementa um operando, eh o incrementador
       do Assembly, soh que no assembly o "inc" ja trabalha em 
       cima dos dados recebidos, incrementando normalmente de "1"
       o operando, basicamente somando "1" aos dados contidos nos
       operandos ou registradore. Usado para se manipular endere_
       cos de memoria. Ex.:

       movl $0x4, %eax # Move "4" para o registrador %EAX
       movl %eax, %ebx # Move o %EAX para o %EBX
       
       inc %ebx        # Incrementa de "1" o registrador %EBX.
                       # %EBX = 5.


* DEC: Esta Instrucao Decrementa um operando, eh o decrementador 
       do asm, e como o "inc" trabalha com os dados ja recebidos,
       decrementando de "1" o operando, basicamente diminuindo "1"
       dos dados contidos nos operandos ou registradores. Tambem
       pode ser usado para se manipular enderecoes de memoria. Ex.:

       movl $0x4, %eax # Move "4" para o registrador %EAX
       movl %eax, %ebx # Move o %EAX para o %EBX

       dec %ebx        # Decrementa de "1" o registrador %EBX.
                       # %EBX = 3 
       


Instrucoes de Comparacao:
-------------------------

Estas Instrucoes sao as instrucoes responsaveis por fazer a 
comparacao de operadores, ou seja, comparacao de dados muda_
ndo assim alguns flags. Sao elas:


* CMP: Esta Instrucao eh usada para se Comparar dados em 
       operandos, ela altera somente as flags, se os ope_
       randos forem iguais o flag de 0 pula p/ 1, ou seja,
       0 a comparacao eh falsa, 1 eh verdadeira. Ex.:
 

       movl $0x3, %eax # Move "3" para o %eax
       movl $0x3, %ebx # Move "3" para o %ebx

       cmp %eax, %ebx # Compara %EAX com %EBX, como sao iguais
                      # o flag serah "1", que quer dizer que sao
                      # iguais.
       jz IGUAL
       jmp DEFERENTE 

       Temos algumas variantes do CMP:

       CMPSB: Esta instrucao eh usada para se comparar "1byte".
       CMPSW: Esta instrucao eh usada para se comparar "1word".


* TEST: Esta Instrucao eh usada para se fazer Comparacoes Logicas,
        com ele se pode comparar o estado de determinados bits, de
        um operando. Ex.:

        movl $0x4, %eax # Move "4" para %eax
         
        test %eax, %eax # Faz uma comparacao, checando o estado dos
                        # bits neste registrador, checando se esta 
                        # tudo 100%, alterando tambem os flags.   


* XORL: Esta Instrucao eh usada para se fazer a Comparacar entre dois
        operandos, zerando o primeiro caso sejam iguais.  Ex.:

        mov $0x2, %eax # Move "2" para %eax. %EAX = 2.
        mov $0x2, %ebx # Move "2" para %ebx. %EBX = 2.

        xorl %eax, %ebx # Como %eax eh igual a %ebx, %EAX eh zerado,
                        # ou seja, Se EAX=EBX, EAX=0, senao EAX=2.



Instrucoes de Salto:
-------------------- 
        
Estas Instrucoes sao usadas para se alterar/mudar a direcao ou
estrutura normal de um programa, sao como o GOTO para o pessoal
do Basic, elas basicamente realizam saltos. Vamos e elas:


* JMP: Esta Instrucao eh usada para se pular/saltar para alguma
       rotina pre-definifa. Eh o JUMP(pula, Salta), eh bastante 
       usado para se fazer saltos incondicionais, fazendo o pro_
       grama executar alguma instrucao diretamente, antes de con_
       tinuar com e sua execucao normal. Ex.: 

       add $0x2, %edx # Move "2" para o %edx
       jmp FUNCAO # Pula/Salta para a FUNCAO. FUNCAO pode ser uma 
                  # declaracao de funcao mesmo, ou um endereco de
                  # memoria de alguma instrucao.

       movl $0xa, %esi # Neste caso esta instrucao nao serah exe_
                       # cutada, pois o jmp o pula antes, ela soh 
                       # sera executada se houver algum outro jmp
                       # o chamando.   

       FUNCAO:         # Eh para aqui que o JMP pula, agora serao 
       #instrucoes     # executadas as instrucoes, apartir deste 
       ...             # ponto.

       Outro Exemplo:

       jmp UIA         # Pula para o label "UIA"  

       UIA:            # Declaracao e inicio do LABEL.
       movl $0x4, %eax # Inicio das instrucoes dentro 
       movl $0x1, %ebx # da rotina/label UIA.
       ... 


Ae vao algumas Instrucoes Equivalentes ao JMP:

JAE: Ela Salta se parametro for acima ou igual aos dados.
JNE: Esta Instrucao Salta se parametro nao for igual.
JGE: Esta Instrucao Salta se parametro for maior ou igual a...
JLE: Esta Instrucao Salta se parametro for menor ou igual a...
JE: Esta Instrucao Salta se parametro for igual a...
JB: Ela Salta se parametro abaixo.
JG: Ela Salta se for maior que...
JL: Ela Salta se for menor que...
JZ: Ela Salta se o parametro acima for igual ao outro,salta
    se parametros iguais, ou seja, se uma comparacao com jz 
    for verdadeira pula para... Ex.:

    movl $0x1, %eax # Move "1" para o %eax
    movl $0x1, %ebx # Move "1" para o %ebx
    cmp %eax, %ebx  # Compara, e como sao iguais, eh verdadeira
    jz IGUAL        # Entao JZ pula para IGUAL
    jmp DEFERENTE   # Se a comparacao fosse falsa, esta instrucao
                    # seria executada, ao inves de jz.

    IGUAL:
    # ponha aqui as suas Instrucoes.
    DEFERENTE:
    # ponha aqui as suas Instrucoes.

Cada uma dessas Intrucoes possuem como parametro, um Label 
de alguma rotina pre-definida ou uma posicao de memoria. Ex.:

jle 0x404890a1 ou jz LABEL1.


* CALL: Esta Instrucao eh usada para se chamar uma sub-rotina, 
        ou mesmo para gerar uma especie de salto para uma ins_ 
        trucao no programa, ele pode chamar um determinado en_
        dereco de memoria ou Label. Ex.:
         

        add $0x2, %edx # Move "2" para o %edx
        call FUNCAO # Pula/Salta para a FUNCAO. FUNCAO pode ser uma 
                    # declaracao de funcao mesmo, ou um endereco de
                    # memoria de alguma instrucao.

        movl $0xa, %esi # Neste caso esta instrucao nao serah exe_
                        # cutada, pois o call o pula antes, ela soh 
                        # sera executada se houver algum outro jmp,
                        # ou call o chamando.   

        FUNCAO:         # Eh para aqui que o CALL pula, agora serao 
        #instrucoes     # executadas as instrucoes, apartir deste 
        ...             # ponto.
 
        Outro Exemplo:
 
        call UIA        # Pula para o label "UIA"  
 
        UIA:            # Declaracao e inicio do LABEL.
        movl $0x4, %eax # Inicio das instrucoes dentro 
        movl $0x1, %ebx # da rotina/label UIA.
        ... 



Instrucoes Logicas:
-------------------

Sao as Instrucoes Logicas responsaveis por se realizar operacoes logicas, 
elas sao usadas para se fazer operacoes Logicas entre os operadores que 
podem ser registradores ou enderecoes de memoria. 
Aih vai uma Comparacao de Instrucoes Logicas:

 C    ASM       
 -    --- 

 &    AND 
 |    OR 
 ~    NOT
 ^    XOR 


Sao Elas:


* AND: Eh o "E" Logico. Ele funciona de acordo com a seguinte Tabela-
       Verdade:

       S = A & B

       A B - S
    
       0 0 = 0
       0 1 = 0
       1 0 = 0
       1 1 = 1

       Veja que o resultado de "S", sera verdadeiro(1), apenas se 
       A "E" B forem 1. Uma das utilidades do AND eh resetar um 
       determinado bit sem afetar os demais. Ex.:

       movl $0x1, %ebx # Move 1byte para o %ebx
       and $3, $ebx    # Reseta o 3bit de %ebx


* OR: Eh o "OU" Logico. Ele funciona de acordo com a seguinte Tabela-    
      Verdade:

      S = A | B
 
      A B - S

      0 0 = 0
      0 1 = 1 
      1 0 = 1
      1 1 = 1

      Note que "S" sera verdadeiro(1), se A "OU" B forem 1. Aplicamos
      esta logica bit a bit envolvendo  um byte ou word atraves de uma
      instrucao em asm, da mesma forma funciona o "and". O OR eh ideal
      para nos setermos um determinado bit sem afetar os demais. Ex.:

      A = 10010101 # A no total 1byte 
      B = 11100011 # B no total 1byte
      S = A & B
      S = 11110111 # Jogando na Tabela-Verdade Temos este resultado.

      Esta eh uma ilustracao do que realmente acontece e os calculos
      feitos. Ex.:

      or %eax, %eax # Igual a 'cmp $0x0, %eax'.


* NOT: Eh o "NAO" Logico. Eh usado para se inverter os bits de um byte 
       ou uma word, ele simplesmente inverte todos os bits. Veja a 
       Tabela Verdade:
   
       S = ~A
       A - S
       0 = 1
       1 = 0       

       Por exemplo se tivessemos um byte com os seguintes bits,
       "10110011" logo apos um NOT, este byte seria entao, "010
       01100". Ex.:

       not %ecx # Inverte todos os bits do registrador %ecx.


* XOR: Eh o "OR" exclusivo. XOR funciona da mesma forma que o "or",
       soh que usado exclusivamente, se apenas 1 variavel tiver re_
       sultado esperado. Bastante usado para se inverter um bit de
       um byte ou uma word sem afetar os demais bits. O 'XOR' eh 
       derivada das 3 instrucoes acima. Veja a tabela-verdade:

       S = A ^ B 
       A B - S  
       0 0 = 0
       0 1 = 1
       1 0 = 1
       1 1 = 0

       O simbola "^" aqui representa o XOR. O xor funfa da mesma forma
       que o or, soh que o resultado serah 1 se Apenas A ou Apenas B
       for 1, ou seja, se ambos forem diferente. Tb util para se alte_
       rar um determinado bit sem afetar os demais. Ex.:

       xor %edx



Instrucoes Gerais:
------------------

As Instrucoes que aqui se encontram sao algumas Instrucoes gerais
que nao entram em nenhum dos topicos acima. Elas sao de uma forma
variada e diferente cada uma com uma determinada acao. Sao Elas: 


* INT: Esta Instrucao eh usada para se gerar uma Interrupcao no 
       sistema, a instrucao "INT" serve de fexo para os seus a_
       grupamentos (argumentos) de instrucoes, executando a fun_
       cao que realmente quer executar. Normalmente o "int" rece_
       be como parametro um numero "hexa". No AT&T usamos o "int 
       0x80" para realizar a funcao de executar, ou seja, passar
       todas as instrucoes ao kernel do sistema, o chamando para
       as executalas. Ex.:

       ...
       movl $0x04, %ecx # Move "4" para o %ecx
       subl $0xa, %esp  # Tira "10" bytes do Stack.

       int $0x80        # Executa, ou seja, chama o kernel para
                        # Executar todas as Instrucoes Acima. 
 



* RET: RET(Return Address), ou seja, Endereco de Retorno. Quando
       um "ret" eh encontrado na sub-rotina a CPU salta de volta
       para a proxima Instrucao a que segue o jmp, ou call, ou 
       seja,ele volta a executar as instrucoes depois do pulo que
       aconteceu com o jmp. ou call. Ex.:

       movl $0xb, %eax # Move "11bytes" para  o %eax
       call PULO       # "call" pula para a sub-rotina "PULO"
       subl $0xa, %esp # Tira 10bytes do Stack Pointer.
       ...

       PULO:           # Inicio da Sub-Rotina "PULO" 
       addl $0xa, %esp # Adiciona 10bytes ao Stack Pointer.
       ...
       ret             # Retorna, executando as Instrucoes 
                       # depois de "call PULO". 
       

* NOP: NOP(No OPeration), ou seja, Nenhuma Operacao. Esta Instrucao
       nao faz ou realiza nenhuma tarefa especifica, somente passa 
       para a Instrucao seguinte. A representacao do "nop" em hexa_
       decimal eh "0x90". Muito usado em exploits para Bufferover_
       flow, onde ele eh usado para se encher o buffer, para ir 
       seguindo ate que se chegue ao shell. Ex.:

       movl $0x4, %eax # Move "4" para o %eax
       addl $0x1, %ebx # Move "1" para o %ebx

       nop  # Passa para a Instrucao seguinte, que eh a "leal ..."   
       
       leal UIA, %ecx # Move UIA pra %ecx
       ... 




--------------
$0x7 - Secoes |
--------------

Um programa Assembly eh dividido em "secoes" tanto depois 
de compilado como antes, as secoes sao usadas para se 
guardar determindo dado, e haver uma certa organizacao na
estrutura de um programa ASM. As secoes sao:


1 - Headers: 
------------

No Assembly existem os "headers", ou seja, os arquivos de cabe_
calho, como no C, no C nos os incluimos com "#include <header.h>"
no Assembly os incluimos com '.include "header.h"'. Pode ser um
arquivo ja existente no sistema ou algum feito por vc com varia_
veis, sub-rotinas, enfim, tudo que vc imaginar. Muito util para
se unir varios arquivos fonte de um mesmo programa. Vai um 
exemplo:

em C:  

#include <stdio.h>

em ASM:

.include "defines.h"


2 - Secao de Dados:
-------------------

Esta secao eh chamada assim por ser onde vao ficar as
variaveis do programa, ou seja, onde vai ficar armazenado  
os dados do programa. Ela eh declarada por ".section .data"
(Secao Dados), com o ".section" declaramos que ali vai
existir uma secao, e com o ".data" declaramos esta secao
com o nome de .data, que eh a secao de dados, no topico
"Exemplos" vc vai entender melhor isto tudo. Ex.:

.section .data

# Aqui viriam os dados, variaveis,etc.
 

2.1 - Variaveis:
----------------

As variaveis como muitos ja sabem, armazenan dados que
podem mudar e que provavelmente serao usadas durante a
execucao do programa. As suas declaracoes e tipos seram
explicadas a baixo.


Declaracao:
-----------

A declaracao das variaveis em Asm, segue a seguinte forma:

NOME: TIPO VALOR ou NOME = VALOR

Onde NOME eh o nome da variavel, o nome que vc usara junto
as Instrucoes, TIPO sao os tipos discutidos a baixo e VALOR
os dados que vao ser armazenados nesta Variavel. Ex.:

VAR1: .long 0
VAR1 = 0 


Tipo das Variaveis:
-------------------

Os Tipos sao, .long, .string, .ascii, entre outras, mas usaremos  
somente essas por enquanto.


.long: Este Tipo eh usado para se definir uma variavel numerica, 
       de ateh 32bits. Ex.:

       NUM: .long 10 # Isto Declara uma Variavel "NUM" do tipo
                     # .long com o valor 10.

       Vamos supor que vc tenha uma variavel texto, chamada VAR2,
       e queira uma variavel com o tamanho da variavel VAR2, coisa
       bastante normal no ASM, faria o seguinte:

       TAM: .long . - VAR2 # Agora a variavel TAM contem o tamanho,
                           # ou a quantidade de caracteres contido
                           # na variavel VAR2.  


.string: Este tipo eh usado para se definir uma variavel texto,
         ou string como quizer, ela aceita caracteres de tabula_
         cao(/t), de newline(/n), etc. Ex.:

         TEXT: .string "-w2x vive em nossos coracoes-\n"
          
         Agora a variavel TEXT contem a nossa String. Agora se
         quisecemos o tamanho de TEXT em uma outra variavel
         fariamos:
 
         TAM2: .long . - TEXT # Pronto, agora a variavel TAM2, tem
                              # a quantidade de caracteres contido
                              # em TEXT. TAM2 = 31. 


.ascii: Este tipo eh usado para se definir uma variavel texto,
        ou string como quizer, ela aceita caracteres de tabula_
        cao(/t), de newline(/n), etc, funciona da mesma forma
        que a .string. Ex.:

        TEXT2: .ascii "-bth, Breaking The Head -\n"


Como foi dito na secao "declaracao", existe uma outra forma
bastante util e rapida de se declarar uma variavel "numerica"
a forma eh "NOME = VALOR", o nome pode ser qualquer um, ele
eh apenas para podermos referenciar, o valor pode ser qualquer
dado numerico, o "valor" pode ser um numero hexadecimal, real, 
inteiro, ou um endereco de memoria, e podem ir ate 32bits. 
Usaremos bastante esta forma. Ex.: 

 write = 0x4  
 stdout = 0x1
 tam = 10
 exitstatus = 0
 exit = 1
 men = 0x8049209


Aih vai um exemplo de como ficaria a "Secao" de dados(.data)
num progranma asm normal:


# Declaracao da Secao Dados.
.section .data

# Variaveis

TEXT1: .string "Isto eh uma String\n"
TAM1: .long . - TEXT1

OFF: .long 0

write = 0x4
exit = 0x1

# Fim da Secao de Dados.



3 - Secao de Codigo, symbols, etc:
----------------------------------

Esta secao eh chamada assim por ser onde vai ficar o
codigo do programa, e informacoes dos symbolos usados
pelo programa, alen de outras informacoes inportantes. 
Ela eh declarada por ".section .text" (Secao Texto), 
com o ".section" declaramos que ali vai existir uma 
secao, e com o ".text" declaramos esta secao com o nome 
de .text, que eh a secao de codigo, no topico "Exemplos" 
vc vai entender melhor isto tudo. Ex.:

.section .text

Esta Secao eh necessaria, um Programa Assembly tem que ter
pelo menos esta secao, pois ela vai ser utilizada para ar_
mazenamento de codigo, tambem do binario. Soh um esclare_
cimento, a secao .text tem que vir depois da declaracao 
da secao .data, e das variaveis. Entao a ordem ficaria,
secao de dados, variaveis, secao de codigo, e logo apos 
a secao principal ou funcao principal que descutiremos
a seguir.  

OBS.: A funcao principal fica dentro da secao de codigos,
      ou seja, ela eh declarada dentro da secao .text, 
      pois afinal eh ali que comeca as instrucoes/codigos
      realmente.

3.1 - Secao Principal, ou Funcao Principal:
-----------------------------------------

O assembly como no C possui uma funcao principal, que eh
onde todas as instrucoes e rotinas serao declaradas e 
iniciadas, eh basicamente o inicio do corpo do programa.
No C a funcao principal eh a main(), no ASM, eh a _start.
A sua declaracao eh feita atraves do ".globl" ou ".global"
como preferir, ou seja vc declara a funcao _start como 
global, ficaria entao, ".global _start", com isso foi 
feita sua declaracao, agora temos que iniciala, e ja pode_
mos iniciar o nosso trabalho, sua inicializacao eh feito 
por "_start:", abaixo disso viriam todas as instrucoes 
que quizesemos. A funcao _start nao pode faltar em nenhum
programa Assembly, e o mesmo sem esta funcao nao irah funci_
onar, ao menos compilar, por isso a sua declaracao e inicia_
lizacao eh obrigatoria, a nao ser que o codigo em questao
seja um header separado, com funcoes e etc, mas o codigo/
arquivo principal, deverah a conter. Ex.:

No C:

int main() {
printf("Ola\n");
}


No ASM:

# Declaramos _start como funcao Global.

.globl _start

# A iniciamos, aqui comeca o nosso trabalho realmente.

_start:

# Nossas Instrucoes, vem aqui.

      movl $0x4, %eax
      movl $0x1, %ebx
      ...(Resto do Codigo)



4 - LABELS:
-----------

Os LABELS sao lugares no codigo que pode ser referenciado 
por uma instrucao ou variavel. Eles sao usados para se 
iniciar uma funcao, ou para se declarar uma Variavel.
Da seguinte forma:

LABEL + ":". Ex.:

LABEL1:

Como variavel:
LABEL2: .long 0

Como funcao:
LABEL3: 
      movl $0x1, %eax
      addl ...



Chegamos ao fim deste Topico se nao entendeu algo, leia
novamente, vamos ver somente como ficaria nosso codigo 
ate aqui. Ficaria entao:


# Inicio do programa.
# Secao de Dados

.section .data

# Variaveis

TEXT: .string "Exemplo com todas as Secoes Juntas\n"
TAM: .long . - TEXT

write = 0x4
exit = 0x1

# Secao de Codigo

.section .text

# Funcao Principal.

.globl _start

_start:

      movl $write, %eax
      movl $0x1, %ebx
      leal TEXT, %ecx
      movl TAM, %edx  
      int $0x80

      movl $exit, %eax
      movl $0x0, %ebx
      int $0x80 

# Fim da funcao Principal
# Fim do programa.


Voce pode compilar e executar este programa pra ver o que 
ele faz, compile com "$ as -o txt.o txt.s","$ ld -o txt
txt.o", logo apos o execute, "$ ./txt", para informacoes
interesantes sobre as secoes e symbolos, alem de algo 
mais, de um "$ objdump -x txt".




--------------------
$0x8 - System Calls |
--------------------


As chamadas de Sistema(System Calls) sao muito usadas no
Assembly, elas sao muito uteis na realizacao de tarefas
pelo programa, vou esplicar como utilizalas, visto que 
vc as utilizara em todos dos seus programas feitos em Asm.
Voce utilizara os system calls do linux no assembly at&t,
os syscall vao ser responsaveis por quase todas as funcoes
dentro de uma programa ASM. Voce encontra uma lista das 
"System Calls" do seu sistema em "/usr/include/asm/unistd.h",
faca uma copia dele pois utilizaremos muito o mesmo para 
consultas. E as mesmas sao executadas por nosso amigo 
"int $0x80", e o valor de retorno para o syscall estarah
no registrador %eax. Voce pode ter ajuda sobre qualquer 
chamada de sistema dando um "$ man 2 syscall" por exemplo 
"$ man 2 write".

Para todos os system calls o "numero" do system call vai em
%eax, e para system calls de ate 6 argumentos, os arqumentos
vao em %ebx, %ecx, %edx, %esi, %edi nesta ordem. O "numero"
dos syscall, vc encontra no arquivo citado acima, "/usr
/include/asm/unistd.h". Vai um exemplo:

Vamos Utilizar o system call "write" para escrever algo
na tela e o "exit" para sair sem problemas. Veja a sinteze
dos dois retirada de "man 2 write" e "man 2 exit":

write:
ssize_t write(int fd, const void *buf, size_t count); 

int fd = Onde ele ira escrever, vai em %ebx
*buff = o que ele ira escrever, vai em %ecx
count = o tamanho do que ele ira escrever, vai em %edx

Ex.: write(fd,"Bth rlz\n",tam);

exit:
void _exit(int status);

status = status da saida, 0, vai em %ebx

O programa assembly para fazer isso seria:


# inicio

.section .data

FRASE: .string "Bth rlz\n"
TAM: .long . - FRASE

.section .text

.globl _start

_start:

 movl $0x4, %eax   # Move o numero do syscall write(4) para o %eax 
 movl $0x1, %ebx   # Onde ele irah escrever, no caso Saida Padrao
                     (Monitor) 
 leal FRASE, %ecx  # O que ele ira escrever, no caso FRASE.                 
 movl TAM, %edx    # O Tamanho do que ele irah escrever.                   
 int $0x80         # No caso %ebx, %ecx, %edx, foram os parametros 
                     de write(4) 

 movl $0x1, %eax  # Move o numero do syscall exit(1) para %eax
 movl $0x0, %ebx  # Status, no caso 0, ou seja, ocorreu tudo certo. 
 int $0x80

# fim

Vamos usar um outro system call aqui para ficar mais clara a utiliza_
cao dos system calls, vamos usar o syscall "open", para abrirmos um
arquivo com o __NR_open fariamos o seguinte:

Sinteze: int open(const char *pathname, int flags, mode_t mode);

    OPEN:
    # Abre o FD(File Descriptor)
    movl $0x05, %eax  # system call open(5)
    movl $FILE, %ebx  # arquivo a abrir, *path
    movl $RDWR, %ecx  # abre para O_RDWR - leitura e escrita, flags
    movl $0x00, %edx  # Perms, mode.
    int $0x80


PS.: Para mais informacoes sobre a chamada de sitema 'open' consulte
a man page do mesmo.

Vemos que os system calls de ate 5 argumentos podem usar este esquema
e serem usados sem problemas. Mas e quando temos system calls que 
possuem mais de 5 argumentos?? Neste caso podemos usar o Stack para 
que ele guarde os nossos argumentos. Vamos a alguns exemplos disso.

As chamadas de sistemas com mais de 6 argumentos, como comentado acima,
o numero do system call vai em %eax, e o retorno da funcao tambem serah
retornada pelo %eax, os argumentos deverao estar na memoria e o ponto 
para o primeiro argumento deve estar em %ebx. Como usaremos o Stack os 
argumentos terao uma ordem de saida e entrada, ou seja, vc deverah 
prestar atencao na ordem ou disposicao dos dados, pois o ultimo a 
entrar serah o primeiro a sair. O Stack Pointer deverah ser copiado 
para o %ebx. Para copiar os arqumentos para o Stack vc terah que 
alocar uma area na memoria e deixar o endereco do primeiro argumento 
em %ebx. 


----------------
$0x9 - Exemplos |
----------------

Todos os exemplo aqui contidos, sao para linux/i386, o fim eh 
somente didatico e conteram comentarios nos codigos, todos os
codigos foram testados e etao funcionando corretamente.
Todos os codigos aqui mostrados podem ser compilados com:

$ as -o <codigo.o> <codigo.s> # Para criar Object File.
$ ld -o <codigo> <codigo.o>   # Para fazer a linkagem. 
$ ./codigo                    # Para Executar ;)


1o - Este exemplo ja foi mostrado no decorrer do txt mas 
mostraremos novamente aqui, ele escreve uma simples 
mensagem na tela:


<++> asm/write.s

# Inicio

.section .data

MSG: .string "Oii Turma, este eh meu 1o code!!\n"
TAM: .long . - MSG

.section .text

.globl _start

_start:

      # Syscall write(4) 
      movl $0x4, %eax 
      movl $0x1, %ebx
      leal MSG, %ecx
      movl TAM, %edx
      int $0x80

      # Syscall exit(1)
      movl $0x1, %eax
      movl $0x0, %ebx
      int $0x80  

# Fim 

<-->


2o - Este codigo abaixo irah usar o syscall 'read' para
ler algo que um usuario digitar e mostrar ele na tela:


<++> asm/read.s

# Inicio

.section .data

MSG1: 
.string "Eu vou ler e escrever o que vc digitar, vc ja pode digitar.\n"
TAM1: .long . - MSG1

.section .text

.globl _start

_start:

      # Syscall write(4)
      movl $0x4, %eax
      movl $0x1, %ebx
      leal MSG1, %ecx
      movl TAM1, %edx
      int $0x80

      # Salva o Stack Pointer em %ecx
      movl %esp, %ecx

      # Reserva 11bytes no Stack
      subl $0xb, %esp

      # Syscall read(3)
      # O q for escrito estarah em %eax
      movl $0x3, %eax # read(3)
      movl $0xa, %edx # Tamanho do que vai ser lido em %edx.
      int $0x80
      
      # Move o que foi digitado para %edx.
      movl %eax, %edx
     
      # Syscall write. Imprime na tela o que foi digitado.
      movl $0x4, %eax
      movl $0x1, %ebx # Saida padrao.
      int $0x80

      # Syscall exit.
      movl $0x1, %eax
      movl $0x0, %ebx
      int $0x80

# Fim

<-->
      

3o - Neste exemplo usaremos 4 chamadas de sitema(syscalls), 
nos basicamente abriremos um arquivo com o syscall open, 
escreveremos nele com o syscall write e fecharemos ele com 
o syscall close, alem da write para escrevermos algumas 
mensagens, veja: 

OBS.: Para que nosso teste com esse programa tenha sucesso
o arquivo "/tmp/open.txt" ja deverah existir visto que nos
soh o abriremos pra escrita, se quizer q ele seja criado 
pelo programa antes, uso o syscall 'creat'. 


<++> asm/open.s

# Inicio

.section .data

MSG1: .string "Nos vamos escrever dentro de /tmp/open.txt\n"
TAM1: .long . - MSG1

MSG2: .string "Aquele filho da mae do hophet escreveu em min!\n" 
TAM2: .long . - MSG2

FILE: .string "/tmp/open.txt"
MODO: .string "O_RDWR"
 
.section .text

.globl _start

_start:
 
      # Syscall write. 
      movl $0x4, %eax 
      movl $0x1, %ebx
      leal MSG1, %ecx
      movl TAM1, %edx  
      int $0x80

      # Syscall open(5) 
      movl $0x5, %eax
      movl $FILE, %ebx # O arquivo ao qual queremos abrir.
      movl $MODO, %ecx # O modo, no caso leitura-escrita.
      movl $0x0, %edx  # Permisao, 0.
      int $0x80

      # Move o retorno da funcao open para %esi.
      movl %eax, %esi

      # Syscall write, irah escrever no arquivo aberto.   
      movl $0x4, %eax
      movl %esi, %ebx # Onde ele irah escrever, no caso o open.txt 
      leal MSG2, %ecx # Irah escrever o conteudo da var. MSG2
      movl TAM2, %edx # O tamanho da variavel.
      int $0x80

      # Syscall close(6), fechara o arquivo.
      movl $0x6, %eax
      movl %esi, %ebx # Fecha o arquivo open.txt
      int $0x80

      # Syscall exit.
      movl $0x0, %eax
      movl $0x1, %ebx
      xchg %eax, %ebx # Troca o conteudo de %eax pelo do %ebx;D
      int $0x80

# Fim

<-->


4o - Neste exemplo farei um codigo que realize uma funcao IF, ele
irah fazer checagens e realizar sua terafa de acordo com o resul_
tado, ou seja, ele irah realizar uma funcao condicional, veja:

OBS.: Mude os valores atribuidos a %eax e %ebx, coloque-os iguais,
faca varias mudancas e veja os resultados.


<++> asm/if.s

# Inicio

.section .data

MSG1: .string "Comparando Registradores...\n"
TAM1: .long . - MSG1

MSG2: .string "Os registradores sao iguais, %eax = %ebx!\n"
TAM2: .long . - MSG2

MSG3: .string "Os registradores sao diferentes, %eax != %ebx!\n"
TAM3: .long . - MSG3

.section .text

.globl _start

_start:

      # Syscall write
      movl $0x4, %eax
      movl $0x1, %ebx
      leal MSG1, %ecx
      movl TAM1, %edx
      int $0x80

      # Atribuindo valores aos registradores. 
      movl $0xa, %eax # %eax eh igual a 10 agora.
      movl $0x8, %ebx # %ebx eh igual a 8 agora.

      cmp %eax, %ebx # Compara os 2 registradores

      jz IGUAL       # Se verdadeira, ou seja, eles forem iguais
                     # jz pula para IGUAL.

      jmp DEFERENTE  # Senao, o que eh obvio, eles forem diferentes
                     # jmp pula para DEFERENTE. 

      # Label
      IGUAL:
 
      # Syscall write
      movl $0x4, %eax
      movl $0x1, %ebx
      leal MSG2, %ecx
      movl TAM2, %edx
      int $0x80

      # Pula para EXIT.
      jmp EXIT

      # Label
      DEFERENTE:

      # Syscall write
      movl $0x4, %eax
      movl $0x1, %ebx
      leal MSG3, %ecx
      movl TAM3, %edx
      int $0x80

      # Label
      EXIT:

      # Syscall exit.
      movl $0x1, %eax
      movl $0x0, %ebx
      int $0x80

# Fim

<-->

     
5o - Neste ultimo exemplo vou fazer um codigo que realize loops, 
seria como uma funcao while() ou for() no C, no caso este progra_
ma vai atribuir 0 a um registrador e irah entrar em uma funcao q
vai incrementar de 1 o registrador e comparalo com 10, assim ele 
vai repetir isso ate que o registrador tenha o valor "10", entran_
do realmente em um loop. Veja:


<++> asm/loops.s

# Inicio

.section .data

MSG1: .string "Iniciando o programa...\n"
TAM1: .long . - MSG1

MSG2: .string "Exemplo de Funcao q realiza Loops!\n"
TAM2: .long . - MSG2

valor = 0

.section .text

.globl _start

_start:

       # Syscall write.
       movl $0x4, %eax
       movl $0x1, %ebx
       leal MSG1, %ecx
       movl TAM1, %edx
       int $0x80

       # Atribui valor de 0, para nosso registrador
       # Igual a movl '$0x0, %esi'
       movl $valor, %esi

       # Label
       INICIO:

       # Syscall write.
       movl $0x4, %eax
       movl $0x1, %ebx
       leal MSG2, %ecx
       movl TAM2, %edx
       int $0x80

       # Incrementa de 1 o registrador %esi.
       inc %esi
       int $0x80

       # Compara %esi com 10
       cmp $0xa, %esi
       jz FIM         # Se igual a 10 pula para FIM.
       jmp INICIO     # Senao volta ao INICIO.
       # Ele vai incrementar ate que %esi seja 10 e assim pular
       # para FIM.


       # Label
       FIM:

       movl $0x1, %eax # Syscall exit.
       movl $0x0, %ebx
       int $0x80

# Fim

<-->

 - Voce pode compilar todos estes exemplos e modificalos para 
   testar o que voce aprendeu, use o extract que veio junto a
   zine para extrair estes codes. 




-------------
$0xa - Links |
-------------

Aih vao algums Links Referentes a Assembly tanto AT&T como 
Intel, vale a pena pesquizar mais sobre o assunto visto que 
este txt eh basico no aprendizado do Asm.


Linux Assembly
http://www.linuxassembly.org/

Assembly's Site
http://www.assembly.8m.com/

Assembly 2001
http://www.assembly.org/

InfoAgora
http://www.infoagora.com.br/

Assembly Programming Journal 
http://asmjournal.freeservers.com/

Mammon's textbase  
http://www.eccentrica.org/Mammon/sprawl/textbase.html

Art Of Assembly 
http://webster.cs.ucr.edu/Page_asm/ArtOfAsm.html

Sandpile - http://www.sandpile.org

GAS
http://www.gnu.org/manual/gas/

NASM  
http://www.cryogen.com/Nasm/

Leto
http://www.leto.net/papers/writing-a-useful-program-with-nasm.txt 

Breaking The Head - Zine
http://www.movl.cjb.net/
http://www.bthzine.cjb.net/

Write To Execute
http://www.write2execute.cjb.net/

Unsekurity Scene
http://www.unsekurity.com.br/
 



------------------
$0xb - Terminando |
------------------ 


Eh, chegamos ao fim deste txt. O estudo do assembly nao se resumi 
a isso, au contrario eh muito mais estenso, por isso consulte os
links acima e procure a maximo de informacao possivel, leia, e o
mais importante 'programe' pq soh assim vc vai aprender realmente.
Assembly eh uma linguagem facinante, vale a pena se aprofundar na
mesma, e acredite com certeza vai ser de grande utilidade pra vc 
nesta vida fucadora. Esta aih o ponta peh inicial, cabe a vcs ago_
ra seguir em frente nesta batalha.

Mao acho interessante nos nos fecharmos e ficarmos cada vez mais
crus, temos que nos unir mesmo que sejamos de grupos distintos,
a troca de informacoes nao pode ter barreiras, vejo pessoas desa_
nimando nesta caminhada(que eh dificil), mas nao impossivel, acho
que temos que ter em mente o que queremos e lutar para chegar ate
o fim, devemos pensar que nada eh tao dificil que pode nos parar, 
e com certeza alcansaremos o "sucesso". Vamos acordar e ver o qto
ainda temos que trabalhar, acho que a troca de informacoes nao po_
de parar, devemos lembrar que varias pessoas presisam dela. Estou
vendo atualmente um cenario totalmente mudado em relacao a antiga_
mente, fucadores sem motivacao, desanimo, Porque??! Enquanto nos
estamos desanimados em trabalhar, e trazer mais informacoes aos
outros fucadores eticos e assim motivalos, estamos parados.
Esperando o que??! E pras pessoas que soh querem falar mau de 
projetos que lutam por isso e sugar informacao de qualidade dos
mesmos, que vcs tomen consciencia, e vejam que o hacking etico
ou hacking verdadeiro vai muito alem do que vcs sabem ou pensam,
o patamar disso, vcs nunca irao alcansar.

Minhas humildes palavras vao ficando por aqui, quero agradecer a 
todo o pessoal do w2x, eSc2, Blood_Sucker, fingu, rpc, hts, 
Minerva, xf, um abraco a todos vcs. Quero mandar um abraco
pros meus irmaos r0ot, sneep, B@bi, fucador, e todos os demais 
do unsekurity ou nao.

Um abraco. []'s




Gustavo vulgo hophet




---------------------------(( EOF ))---------------------------
  



 











