You are on page 1of 10

Olá a todos...

Bom...antes de começarmos com o nosso "breve" tutorial de assembly, preciso fazer algumas considerações.
Assembly é uma linguagem de baixo nível (só lembrando: quanto mais ALTO for o nível de uma linguagem, mais
perto da escrita humana, portanto, mais FÁCIL de entende-la e utiliza-la). Portanto, talvez você tenha que ler
várias vezes esse tópico pra entender. Mas acreditem, Assembly é MUITO útil.
Outra coisa que gostaria de esclarecer é que algumas pessoas escrevem (e falam) o nome da linguagem de
maneira errada, o nome da linguagem é ASSEMBLY, muitas pessoas a chamam de Assembler. Assembler é o
"compilador" e não a linguagem. :)

>>>Conhecendo a linguagem<<<
Assembly é uma linguagem de programação extremamente poderosa e relativamente de difícil implementação,
pois seus comandos e suas estruturas são bem mais próximos da linguagem computacional. Raramente
encontramos programas puramente feitos em Assembly, uma vez que tal linguagem exige tempo e muito
raciocínio. Geralmente essa poderosa linguagem é implementada junto a alguma outra, funciona como auxiliar.
Por exemplo, em programas que exigem uma interação mais profunda com o hardware de uma máquina,
podemos implementar códigos Assembly junto ao código em C, C++ ou qualquer que seja a linguagem utilizada.
Outro exemplo prático do uso de Assembly são os famosos ShellCodes presentes nos exploits. E ainda, como
último exemplo, temos os nossos amigos “Reversers” (popularmente chamados de “crackers”, pois crackeiam
programas) que usam muito o Assembly. Um bom “reverser” (“cracker”) sabe profundamente Assembly ;)

Todos os processadores possuem uma "linguagem" própria embutida em cada um deles e cada instrução
(comando) dessa linguagem produz um efeito diferente no processador, através de seus registradores. Essas
instruções são representadas por números como, por exemplo, a famosa instrução MOV DL é representada pelo
número B2 em hexadecimal (178 em decimal). Esses números, em Assembly, são trasnformados nos chamados
mnemônicos para uma maior facilidade. Por exemplo, ao invés de você escrever B2 e ter de decorar o que é cada
número, você vai escrever o mnemônico dele que, nesse caso, é o MOV DL. Onde MOV significa MOVer e DL é o
chamado byte baixo de um outro registrador (DX).

"Meu Deus! Fiquei espantado com essa introdução!!! Assembly é difícil demais!!"

Tenha calma...Assembly não é aquele bicho de sete cabeças como todos dizem(e como parece ser também)...no
começo parece que você não vai entender nada, mas depois as coisas começam clarear e você vai entendendo
cada vez mais, até que começa a realmente utilizá-lo em seus projetos.

Bom...vamos em frente...temos bastante chão ainda :D

>>> Registradores <<<


Quem já deu uma fuçada nessa linguagem de programação, com certeza ouviu falar dos famosos
Registradores...

Mas, Black-Hat, o que são os tais registradores??

Bom...uma das maneiras mais fáceis de explicar um registrador é compará-lo a uma variável, eles são como
"espacinhos" reservados dentro do processador para guardar os códigos operacionais (MOV, JMP, NOP...), são
uma espécie de "memória" temporária do processador.
Existem vários registradores, deles, os mais usados são 8, que são denominados Registradores de Uso Geral.
Mas desses 8, os que realmente se utiliza bastante são apenas 4, são eles: AX, BX, CX e DX.
Um registrador armazena 16 bits, o que é correspondente a 2 bytes. Nas máquinas de 32 bits, temos o EAX, o
EBX, o ECX e o EDX que são registradores que podem guardar 32 bits (segundo a matemática avançada, o
equivalente a 4 bytes, pois 32/8 = 4 uahSIUHauhs).
Os nomes dos registradores sugerem pra que servem, o AX é o Acumulador, o BX é a Base, o CX é o Contador e
o DX possui um D que deriva de Dados. Esses nomes surgiram devido ao uso mais comum deles, o AX é mais
utilizado como acumulador, BX como base e etc...

"Aff Black-Hat, não aguento mais ler..." ... Calma, tá acabando (a parte de registradores ;P)

Bom...como eu havia dito, os registradores armazenam 2 bytes, que são chamados de Byte Alto e Byte Baixo,
cada registrador possui o seu BA e o seu BB. Se quisermos acessar o byte alto do registrador AX, por exemplo,
vamos utilizar o AH e observem que, mais uma vez o nome não está aí a toa...Alto em inglês é High e por isso
AH. Se quisermos acessar o byte baixo de AX, utilizamos o AL (baixo em inglês é Low).
Pronto!! Agora SÓ falta vermos as instruções, as variáveis, saltos...e mais umas coisinhas :D
Prepare-se psicologicamente, vá beber uma água ou namorar um pouco...porque agora começa a parte mais
importante (e mais legal tbm xD).

Vamos falar sobre as instruções mais utilizadas: a MOV e a INT.

>>> A Instrução MOV <<<


A instrução MOV, uma das mais utilizadas, deriva da palavra MOVe, então, já da pra saber o que ela faz, né? Ela
move dados de um lugar para outro(de um registrador para outro, por exemplo) ou insere dados nos
registradores. Alguns exemplos de utilização da nossa querida instrução MOV:

MOV AX, 01 //Insere o valor 1 no registrador AX


MOV BX, AX //Move o que estava em AX para BX
MOV AH, 0x20 //Insere o valor 20 em HEXA no byte alto de AX
MOV BL, 0x43 //Insere o valor 43 em Hexa no byte baixo de BX

Simples... =)

>>> A Instrução INT <<<


A instrução INT chama uma interrupção de software(calma, não se desespere com o nome...vc não vai precisar
desse nome).
Tá, mas, pra que serve isso afinal??
O DOS e a BIOS do seu computador e de todos têm várias funções interessantes que podemos acessar com
interrupções de software.
Por exemplo:
INT 0x21 ;Chama a interrupção de software 21 Hexa

Agora um programa BEMMMM básico(não chega nem a ser um Hello World):


MOV AX, 0x4C00 ; Insere 4C00 no registrador AX, que armazena 4 bytes(em máquinas de 32 bits)
INT 0x21 ; chama a interrupção 21 de software

O que esse programa faz? Bom...ele simplesmente termina (não, eu não estou bebado...ele nao faz nada alem
de terminar)

Bom pessoal...vocês devem estar se perguntando porque eu chamei a interrupção 21 e não a 55, por exemplo.
Bom...pra explicar isso vou precisar da ajuda de um "livrinho virtual", uma referência, que se chama HelpPC...
Vou deixar o link de download pra vcs baixarem, ok? (não vou anexar porque o limite maximo de anexo Zip é
menor do que o tamanho do arquivo)
Assim podemos continuar...

Link: [Somente usuários registrados podem ver os Links]

Continuando....

Ao abrirmos o HelpPC, caimos em uma tela inicial, chamada de Main Topic Menu. Vá até o item "Interrupt
Services DOS-BIOS-EMS-Mouse" e de um enter nele. Agora vá em "DOS Functions" e aperte enter novamente.
Procure pela função que utilizamos acima, a "INT 21,4C".
Bom...agora estamos na tela que nos mostra informações detalhadas sobre tal função, podemos observar que
essa função recebe o nome de "Terminate Process With Return Code", traduzindo: Terminar Processo Com
Código de Retorno. Olhando melhor na tela, percebemos que o HelpPC nos indica que o byte alto de AX deve ter
o valor 4C e que o valor baixo deve ter o código de retorno do nosso programa. Quem programa em C/C++ já
sabe o que é o código de retorno do programa...é um código, um número, que o programa retorn a ao ser
finalizado. Observamos também qeu a função 21 não retorna nenhum valor (o que seria chamado de rotina em
outras linguagens).
Resumindo...para usar essa função, basta você colocar os valores que são exijidos no registrador AX e depois
disso é só chamar uma interrupção de software 21 (INT 0x21).

Caso você esteja super curioso pra ver o nosso "programa" funcionar, baixe o NASM e compile-o, como?
simples...
Salve o código fonte dele como Terminator.asm no bloco de notas ou com qualquer outro nome que queira...
Depois vá no DOS e digite:
nasm -o Terminator.com Terminator.asm
e então você obterá o seu super programa compilado no arquivo Terminator.com =)

Tá...vamos fazer um programa um pouco melhorzinho...ele vai escrever um caractere na tela...

Se procurarmos no HelpPC a função que escreve um caractere na tela vamos achar a INT 21,2.
Observem que precisamos do valor 02 no byte alto de AX (AH) e precisamos que o caractere a ser mostrado
esteja no byte baixo de DX (DL). Pronto! Agora é só fazer isso...Let's Go

MOV AH,2 ; Serviço 2 da interrupção 21


MOV DL,'A' ; Caractere que deve ser impresso
int 0x21 ; Chama a interrupção 21 e imprime na tela

Bom...nosso programa precisa terminar ... basta adicionar o código do programa anterior...Ficando assim:

MOV AH,2 ; Serviço 2 da interrupção 21


MOV DL,'A' ; Caractere que deve ser impresso
INT 0x21 ; Chama a interrupção 21 e imprime na tela
MOV AX, 0x4C00
INT 0x21

Agora é só compilar e boa! =)

Obs.: Caso você tenha algum problema com a compilação, retire os comentários do código-fonte.

Bom...Chegamos na metade!!! UHULLL


uahSUHauihsuihs
Sim...o tópico está enorme e cansativo, mas vc quer aprender? vc tem que ler né?? ;P
Vamos em frente...
Até aqui foi fácil né? Que bom...vamos "engrossar o caldo" agora xD

>>> As Variáveis <<<


Bom...o conceito de variável em assembly é o mesmo das outras linguagens de programação, com pouca
diferença, então acho que não teremos problemas com elas. Em Assembly, os dados são inseridos diretamente
no programa e são rotulados com um nome que você quiser (semelhante às outras linguagens xD). Os tipos de
variáveis são:
Byte(B) = 8 bits = 1 byte
Word(W) = 16 bits = 2 bytes
DWord(D) = 32 bits = 4 bytes
Agora vamos ver como "declarar" as variáveis. Iremos utilizar DB, DW e DD (Byte, Word e Double Word)
Alguns exemplos:

varbyte DB 0 ; 1 byte chamado "varbyte" é inserido


varword DW 0 ; 1 word chamado "varword" é inserido
vardouble DD 0 ; 1 duplo chamado "vardouble" é inserido

bb DB 0,1 ; 2 bytes chamados "bb" são inseridos


word3 DW 1,1,1 ; 3 words chamados "word3" são inseridos

strg DB 'abcd' ; uma string de 4 bytes chamada "strg" é inserida


Não tem segredo :)

Agora vamos ver como manipular nossas variáveis:

MOV AL, 15 ; Insere 15 no byte baixo de AX


MOV [varbyte], AL ; Move 15 para a variável varbyte

MOV BX, 0x8765 ; Insere 8765 hexa em BX


MOV [varword], BX ; Move o valor de BX para a variavel varword

MOV [bb], BX ; O valor de "bb" se torna 0x8765


MOV BH, [bb] ; BH = Primeiro byte em "bb" = 0x65
MOV BL, [bb+1] ; BL = Segundo byte em "bb" = 0x87

MOV DL, [strg] ; DL = Primeiro byte em "strg" = 'a'


MOV DL, [strg+1] ; DL = Segundo byte em "strg" = 'b'
MOV DL, [strg+2] ; DL = Terceiro byte em "strg" = 'c'
MOV DL, [strg+3] ; DL = Quarto byte em "strg" = 'd'

Quando quisermos pegar o valor das variáveis, tiramos os colchetes, assim:

MOV DX, strg ; DX = Coloca em DX o valor de "strg"(na verdade DX se torna um ponteiro para strg, cada vez
que nos referimos a ele, ele aponta pra strg)
MOV AL, [DX] ; AL = Primeiro byte em "strg" = 'a'

--Vamos escrever uma string na tela--

Essa parte parece perda de tempo, mas não é, ela será essencial para a próxima parte....portanto, vamos
escrever a nossa string na tela xD
Se procurarmos no HelpPC a função que imprime caracteres na tela, vamos encontrar a INT 21,9 (serviço 9 da
interrupção 21).
Então, de repente, você olha pra tela e ve que o DSX tem que apontar para uma string terminada em $ (MEU
DEUSSS!!! O QUE É ISSO??). Bom...vamos ignorar o tal do DSX por enquanto, nao se assuste, eu avisei que ia
complicar um pouquinho...mas nada que um cérebro não resolva...
Bom...o DX precisa conter o endereço da string que vamos exibir(precisa ser um ponteiro para a string).
Bom...como vocês sabem...esse programa é um programa DOS, roda no "console" do windows...entao temos
algumas coisas que devemos lembrar:
Todo programa DOS é carregado no endereço 0x100. O NASM precisa de um endereço para calcular o valor dos
ponteiros no programa, entao temos que dizer ao NASM que o nosso endereço base (endereço onde o programa
será carregado) é o 0x100, como? usando o comando ORG (derivado de ORiGem), assim:

[ORG 0x100]

pronto...agora o NASM sabe o endereço base e pode calcular o valor dos ponteiros =)

Então agora MÃO NA MASSA...

MOV AH, 9 ; AH deve ser 9 para a int 21 imprimir uma string


MOV DX, msg ; DX=Ponteiro para msg
INT 0x21

MOV AX, 0x4C00 ; Termina o programa


INT 0x21

msg DB 'HelloWorld!$' ; Insere a mensagem que é uma string terminada em "$"


Uffa...acabamos variáveis =)
Tá começando a ficar mais interessante né? :D
Então vamos complicar mais, para ficar mais interessante...

>>>Entrada do teclado<<<
Abrimos o HelpPC felizes e contentes, procuramos por uma funçao que pegue as teclas digitadas...e então
encontramos a função DOS 21,A. Oba! vamos entrar nela...PELAS BARBAS DO PROFETA!!!(expressão de véio) O
QUE SÃO ESSES "BAGULHOS" ESCRITOS AQUI???
Haha...contenha-se...eu sei seu sei...parece complicado, mas você é um hacker, você vai entender...

Bom...olhando para a tela de informações sobre a função, DSX deve ser um ponteiro para um buffer com 3
partes:
-MAX : o numero maximo de caracteres que devem ser lidos
-COUNT : o número de caracteres retornados
-BUFFER : a parte aonde os dados serão guardados

Dessa vez vai ser diferente, primeiro o código para ajudar-nos:


[ORG 0x100]

MOV AH, 9 ; Imprime "Escreva aqui: "


MOV DX, msgentrada ;
INT 0x21 ;

MOV AH, 0xA ; Guarda as teclas digitadas


MOV DX, buff ; e armazena no buffer
INT 0x21 ;

MOV AX, 0x4C00 ; Termina o programa


INT 0x21 ;

msgentrada DB 'Escreva aqui: $'

; E finalmente o buffer
buff:
max DB 20
count DB 0
data DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

Calma...eu sei que parece uma coisa estranha...vou explicar :)

Na área max definimos o número máximo de teclas que o buffer pode guardar, que no nosso caso é 20. E como
colocamos 20 como tamanho máximo, colocamos também 20 zeros na área data. Para o programa parar, aperte
Enter.

Ok...agora vamos ver mais uma coisa bem importante =)

>>> Os Jumps (Saltos) <<<


Os jumps, como o próprio nome diz, servem para fazer saltos de uma parte do código para outra (esse processo
é conhecido como "devio da linha de execução"). Geralmente são condicionais, ou seja, funcionam mais ou
menos como se fossem um comando "If", utilizado para checar se certas condições são verdadeiras ou falsas,
mas também há o chamado salto incondicional, que não depende de nenhuma condição para ser tomado.
Os mais utilizados:

JE - Salta se for igual (Equal)


JNE - Salta se for diferente (Not Equal)
JZ - Salta se for zero
JNZ - Salta se não for zero
JA - Salta se acima (Above)
JAE - Salta se acima ou igual (Above or Equal)
JB - Salta se abaixo (Below)
JBE - Salta se abaixo ou igual (Below or Equal)
JNA - Salta se não acima (Not Above)
JNB - Salta se não abaixo (Not Below)
JMP - Salto Incondicional

Bom...para fazer as comparações, precisamos utilizar uma outra instrução, a instrução CMP (derivada de
CoMPare). Nada como um exemplo para entendermos melhor a integração do CMP com o JMP.

[ORG 0x100]

MOV CX, 0 ; CX é o contador, colocamos 0 nele

Escreve: ; marcador chamado Escreve, para o programa saber para onde direcionar o salto
MOV AH, 9 ; Escrever mensagem
MOV DX, msg
INT 0x21

INC CX ; CX é o contador e a instrução INC vem de Increase, Incrementar (CX = CX +1)

CMP CX, 5 ; Compara o valor de CX com 5


JNE Escreve ; Caso o contador seja diferente de 5, salta para Escreve e repete tudo até chegar no salto
novamente

MOV AX, 0x4C00 ; Termina o programa


INT 0x21

msg DB 'BELEZA!',13,10,'$' ; A string contém o código 13,10, que faz com que o console passe para a próxima
linha

Se você pensar e observar um pouco, você descobre o que o programa faz...Vamos analisar juntos...
Primeiramente o programa escreve a string msg na tela, em seguida adiciona 1 no valor do contador CX e então,
compara o valor de CX com 5, caso não seja 5, escreve a string de novo e adiciona mais 1 ao contador CX...E
assim vai até que isso tenha sido feito 5 vezes, daí o contador terá valor 5 e o salto não será executado, o
programa continuará executando o código normalmente, que no caso, fecha o programa.

Legal né? Então agora vamos conversar um pouco sobre as Funções =)

>>> As Funções <<<


No exemplo acima, definimos uma parte do código chamada "Escreve", isso se chama marcador. As funções em
Assembly são parecidas com marcadores, porém, têm instrução de retorno e não se utiliza jumps mas, sim, a
chamamos no código. Uma função pode exigir parâmetros e é para isso que serve a famosa Pilha e também os
Registradores, para passarmos os parâmetros exijidos na função. Funções são comumente usadas em tarefas
repetitivas.
Aqui um breve exemplo de como usar este recurso:

[ORG 0x100]
CALL funcao ; Chama a função

MOV AX, 0x4C00 ; Termina o programa


INT 0x21 ;

funcao: ; Começo da função


; aqui colocamos o código que será executado
RETN ; Essa instrução indica o fim de uma função, dizendo ao programa para sair do código da função e retornar
ao código principal do programa

Pode até parecer complicado, mas é fácil. Conforme você for praticando, você vai "pegando o jeito" de trabalhar
com funções, comparações, saltos...

=)

Ei!! Está pensando o mesmo que eu?? Podemos melhorar aquele nosso programa que grava as teclas digitadas,
utilizando jumps e comparações...

Vamos lá...vou colocar o código comentado aqui, analise-o com calma e entenda o que cada instrução faz, não
será preciso eu ficar explicando pra que serve cada instrução...você já as conhece...

[ORG 0x100]

comeco:
MOV AH, 9 ; Serviço 9 (de impressão) da INT 21
MOV DX, msg1 ; Coloca o DX como ponteiro para a mensagem "Digite Algo: "
INT 0x21 ; Chama a interrupção e escreve na tela

teclas:
MOV AH, 0x1 ; Serviço 1 da função 21, para rastrear uma tecla
INT 0x21

CMP AL,13 ; o código da tecla é gravada em AL. Se for 13(enter)...


JE final ; Salte para o marcador "final"
CMP AL, 27 ; Se for Esc
JE fechar ; termina o programa
MOV [data+bx], AL ; põe caracter da tecla no buffer
MOV BL, [count] ; põe número já digitado em BL
INC BX ; incrementa número de caracteres
MOV [count], BL; atualiza o count
CMP BL, 20 ; se o número de caracteres for 20....
JE final ; Pular para o marcador "final"
JMP teclas ; Case nenhum jump acima seja tomado, salta para o marcador "teclas" e espera uma nova tecla

final:
MOV AL, '$' ; Põe o caractere terminador '$' em AL
MOV BL, [count] ; Põe número de teclas digitadas em BL
MOV BH, 0 ; Zera o byte alto de BX
MOV [data+bx], AL ; Adiciona o '$' no final do buffer

MOV AH, 9 ; Serviço 9 da interrupção 21


MOV DX, msg2 ; DX = ponteiro para msg2
INT 0x21 ; Escreve msg2 ("Texto digitado: ") na tela

MOV AH, 9 ; Serviço 9 da função 21


MOV DX, data ; DX = ponteiro para os dados do buffer
INT 0x21

XOR BX,BX ; Zera o registrador BX (mesma coisa que MOV BX,0)


MOV BL, 20 ; Máximo de caracteres (20)
XOR AX,AX ; Zera o registrador AX
MOV [count], AL ; Zera o contador

limpar:
MOV [data+bx], AL ; Põe 0 na posição início do buffer + BL
DEC BL ; Decrementa BL
CMP BL, 0 ; Compara BL com 0
JA limpar ; Se for maior que 0 continua limpando o buffer

JMP comeco ; Se BL for 0, volta para "comeco" e reescreve "Digite Algo: "

fechar:
MOV AX, 0x4c00 ; terminar programa
INT 0x21

; Os caracteres 13 e 10 forçam uma nova linha


msg1 DB 13,10,13,10,'Digite Algo: $'
msg2 DB 13,10,'Texto Digitado: $'

; Este é o buffer de entrada com espaço para 20 bytes para caracteres


; e 1 byte para '$'
buf:
count DB 0
data DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

O código está bem comentado e acho que vocês não terão problemas em interpreta-lo...Vamos ao nosso próximo
assunto...

>>> A Pilha <<<


A pilha é um lugar na memória do processador, que serve para guardar dados. Usamos a instrução PUSH para
colocar dados na pilha e POP para retirar. Lembra daquela famosa frase: "Os últimos serão os primeiros" ?
Pois é...essa é a regra quando se usa a Pilha...os dados são retirados na ordem inversa que foram colocados.
Imagine que você tem 4 pratos, um laranja, um azul, um verde e um amarelo.
Você vai fazer uma pilha com esses pratos...então primeiro você coloca o amarelo, depois o verde, depois o azul
e em cima de todos, o laranja. Agora você vai retirar de 1 em 1, quando você começar a retirar, o primeiro a ser
retirado é o que está em cima, o laranja (o último que foi colocado). Assim funciona a pilha...
Lembra da instrução CALL? Aquela que chama uma função? Espero que sim...
Lembra também que toda função, no seu final, possui a instrução RETN?
Então...um exemplo de uso da pilha é o seguinte: quando você utiliza a função CALL, ela guarda na pilha o
endereço de retorno, sendo assim, quando a instrução RETN for atingida, o programa saberá pra qual endereço
deve voltar...

Como sempre, vamos a um exemplo básico:

MOV AX, 456


MOV BX, 789

PUSH AX ; Coloca o valor de AX na pilha, que é 456


PUSH BX ; Coloca o valor de BX na pilha, que é 789
POP AX ; AX = Valor que está no topo da pilha = 789
POP BX ; BX = Valor que está no topo da pilha = 456

Observe que colocamos o valor 456 e, em cima, colocamos o valor 789... na hora que retiramos da pilha,
primeiro retiramos o valor 789(ques estava no topo da pilha) e dps tiramos o que estava embaixo, o 456, que
havia sido o primeiro a ser colocado.

Super simples né? xD


Vamos continuar complicando mais as coisas então...só faltam mais 2 assuntos para acabarmos... :)

>>> Os Segmentos <<<


Bom...como sabemos, os pentes de memória de hoje em dia conseguem armazenar até milhares de megabytes,
um número estupendamente maior do que o que é possível com 16 bits...
Em 16 bits, temos 2 bytes e , cada byte é um conjunto de 8 números binários(8 bits), logo, o número máximo
que conseguimos com 2 bytes em binário é: 1111 1111 1111 1111, este número é o 65535 em decimal, que
corresponde a 64 Kb, muitas vezes inferior ao número de megabytes que as memórias de hoje possuem...

A memória tem suas posições, mas desde que as memórias melhoraram e ficaram capazes de armazenar muitos
MB, surgiu um problema...como fazer com as posições que ficam acima dos 64 Kb, isto é, o que fazer com as
posições acima da posição 65535?
A solução foi dividir a memória em "lotes" (segmentos) de 65536 bytes (de 0 a 65535).

Primeiramente os segmentos foram colocados um após o outro: o Segmento 1 começa na posição 0 e vai até a
65535, o Segmento 1 começa em 65536 e vai até a 131071...e assim por diante...

Quando quisessemos acessar uma posição, utilizariamos 2 números, um para indicarmos o segmento que iriamos
acessar e o outro para indicarmos a posição dentro desse segmento...
Só que houve um segundo problema...ao colocarmos os segmentos um após o outro, haviam programas que
quando utilizavam a memória, não utilizavam todo o segmento...então a memória ficava cheia de "buracos" sem
dados gravados...

Foi aí que surgiu uma nova idéia...colocar os segmenos um em cima do outro, dando um espaço de 16 bits entre
o começo de um e o começo do outro...
Então agora o Segmento 0 começa na posição 0 e vai até 65535, O Segmento 1 começa na posição 16 e vai até
65551...

O Segmento x começa na posição x*16 e vai até a posição x*16 + 65535 :D

Pronto...agora você sabe(ou não IUaHSIUAHS) como a memória do seu pc é dividida...não é fantástico? ;P

Finalmente...chegamos ao último assunto... :D

>>> Deslocamento <<<


O deslocamento, chamado de OffSet é um endereço que muda de acordo com o segmento e serve para indicar
um byte dentro das 65536 posições disponíveis (lembre-se que as posições vão de 0 a 65535 e temos de incluir
o 0, o que resulta em 65536 posições possíveis).
Mesmo depois da mudança na divisão da memória, ainda usamos dois endereços para definir uma posição na
memória...
Vamos a um exemplo de como indicar posições na memória...

Endereço 2345:6789 --> Segmento 2345 , Deslocamento 6789

Ou seja, é a posição 6789 dentro do segmento 2345

O segmento começa na posição 37520 (2345*16) da memória e o nosso deslocamento dentro do segmento é de
6789, ou seja, 6789 posições à frente do começo do segmento. Se o segmento começa em 37520, a posição que
queremos (6789 posições à frente) fica no endereço 44309 da memória... xDD

Bom...o seu processador, muito esperto, possui registradores especiais para lidar com os segmentos, o principais
são: CS(Code Segment) , DS(Data Segment) , ES(Extra Segment)...O CS gerencia aonde está o código do
programa, o DS gerencia aonde estão os dados do programa e o ES, como o nome diz, é um adicional.
Também há um registrador para gerenciar o deslocamento...o SI(Segment Index)
Quando queremos acessar um dado do programa, utilizamos a dupla DS:SI, onde DS diz o segmento que está o
dado e o SI diz o deslocamento dentro do segmento em questão....
Não há instruções que alterem diretamente esses registradores...se um programador distraído bagunçar esses
registradores ou se um programador inexperiente resolver "xeretar" eles e alterar de forma indevida, os
resultados serão EXTREMAMENTE DANOSOS...entao é justamente por isso que, caso o programador queira
altera-los, terá de fazer de forma indireta, oq eu certamente vai exigir mais atenção e evitar erros acidentais...

Vamos ao exemplo de como alterar os valores... (lembre-se: nunca brinque com assembly por conta própria,
principalmente quando se trata de operações com memória)

MOV AX, 1000 ; AX = 1000


MOV DS, AX ; Altera o número do DS (segmento de dados) para 1000

MOV AX, [ds:0] ; Põe word do endereço 1000:0000 em AX - endereço 16000


MOV [1234], AX ; Põe valor de AX no segmento atual no deslocamento 1234

INC AX ; Incrementa AX
MOV [ds:32], AX ; Põe valor de AX no endereço 1000:0032 - endereço 16032

FINALMENTE!!! Chegamos ao fim do nosso artigo...


Gostaria de deixar claro que este artigo é de exclusiva autoria MINHA para o Guia do Hacker, tudo o que está aí
saiu da minha cabeça...portanto não tenho créditos a colocar.
Se você for copiar, coloque os créditos... =)
Você vai encontrar outros artigos e referências que seguem a mesma sequencia que este, assim como utiliza
exemplos bem parecidos. A razão disso é clara, existe uma sequencia mais didática para se fazer um artigo
qualquer...por exemplo, eu não poderia falar sobre a instrução INT antes de lhe falar o que e pra que serve um
registrador...quanto aos exemplos...é claro que alguem que nem conheço em algum outro artigo deve ter feito
exemplos parecidos...isso é normal...nao tem muito o que variar nesses exemplos básicos... :)

Bom...acho que depois de ter tido paciência (e muita!) e lido esse artigo, você agora viu que Assembly não é
algo de outro mundo...obviamente é uma linguagem difícil, mas não é impossível de se aprender.
Aqui coloquei as coisas básicas de Assembly, o necessário para você começar...a partir de agora a
responsabilidade de aprender mais é sua, tente fazer programas com outras funções, para isso use SEMPRE o
HelpPC...
Depois que você dominar BEM esses conceitos básicos, passe para uma parte mais avançada da linguagem, com
intruções e interrupções mais complicadas e até tente aprender a programar ShellCodes...Mas tenha calma, o
segredo de um bom programador é fazer as coisas em passos para alcançar seus objetivos...não se atropele,
siga o seu ritmo e chegue aonde você quer!

Espero que gostem do meu artigo, deu um trabalho legal para escrever ele, mas espero que seja de grande
utilidade para vocês. :D

You might also like