Unconfigured Ad Widget

Collapse

Anúncio

Collapse
No announcement yet.

Guia Assembly - feito por mim ;)

Collapse
This is a sticky topic.
X
X
 
  • Filter
  • Tempo
  • Show
Clear All
new posts

  • Font Size
    #1

    Guia Assembly - feito por mim ;)

    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


    >>> 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
    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:

    Código:
    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:
    Código:
    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):
    Código:
    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: Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...


    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 retorna 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

    Código:
    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:

    Código:
    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:

    Código:
    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:

    Código:
    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:
    Código:
    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:

    Código:
    [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...

    Código:
    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é?
    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:
    Código:
    [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:
    Código:
    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.

    Código:
    [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:

    Código:
    [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...

    Código:
    [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:

    Código:
    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

    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...


    >>> 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)

    Código:
    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.


    Abraço a todos...


    Flws
    Black-Hat.
    Similar Threads

  • Font Size
    #2
    GRANDE tutorial kkkkkk
    muito bom
    valeu por postar



    Durante os tempos de mentiras universais, dizer a verdade se torna um ato revolucionário

    Comment


    • Font Size
      #3
      @Black-Hat

      Eu li seu tutorial de como converter números para bases diferentes... eu gostei muito...

      ^^

      Agora vou ler este guia feito por você. Tomara que esteja tão bom quanto o outro tópico seu ^^

      xD
      Att,

      [A]ntharaz



      sigpic

      Comment


      • Font Size
        #4
        @Antharaz

        Opa, brigado =)

        Espero que goste desse também...é bom saber que meus posts estão sendo úteis xD

        Flws
        Black-Hat.

        Comment


        • Font Size
          #5
          Vou da uma lida no seu trabalho, li rapido, mas parece que vc entende mesmo..
          Parabéns e valeu por compartilhar conosco...

          Abraços

          Comment


          • Font Size
            #6
            Gostei do artigo, bem didático e explicativo (Lí ele todo!), me ajudou a esclarecer algumas dúvidas no qual achava ser diferente ou mais complicado, como por exemplo a explicação da divisão da memória/Segmento/offSet.

            Obrigado mesmo, muito útil seu artigo.

            []'s;

            Comment


            • Font Size
              #7
              Nossa esse tuto me lembro as velhas pérolas que a galera distribuia antigamente nos fóruns gringos ou em e-zines, pqp muito bom, até quem não saca muito de programação pode entender ele se esforçar-se um pouco, ao contrário do que muitos dizem ASM "não é tão difícil" não que eu seja um expert no assunto só sei fundamentos da linguagem e coisas bem básicas pois nunca pude me dedicar a ela, simplesmente OBRIGADO pelo tuto e saiba que os seus tutos são os melhores do fórum e principalemtne feitos pro vc e não ctrl+c e ctrl+v como a maioria dos outros que se vê por aí.
              Parabéns mesmo
              []s
              <<< ENGINEERING CODERZ - HACKING PROGRAMMING GROUP >>>
              msn/mail: azurus21@gmail.com

              Comment


              • Font Size
                #8
                To me iniciando no Assembly...esse seu tutorial está sendo bem util...vlw
                "Torna-te aquilo que és."

                Comment


                • Font Size
                  #9
                  Bom,só li o começo mas parece ser interessante.
                  A...uma pequena correção:"Assembler é o 'compilador' e não a linguagem.".Assembler é o Assembler.Transforma códigos escritos em assembly em código de máquina.
                  No mais,assembly só é dificil antes de aprender,depois parece que fica tão ridiculo...

                  Comment


                  • Font Size
                    #10
                    bom você poderia explicar mais sobre os segmentos e a pilha que não esta muito legal mais o resto fico legal

                    Comment


                    • Font Size
                      #11
                      Po excelente, favoritei no navegador, estou lendo com cuidado aqui... Excelente trabalho!!

                      Comment


                      • Font Size
                        #12
                        òtimo topico para iniciantes!

                        Bom cara estou começando nesse mundo da programação, quer aprender assembly para poder criar cheats e hacks para jogos e seu tutorial era o que eu procurava apos dias de pesquisa encontrei o que necessitava muito legal!

                        Comment


                        • Font Size
                          #13
                          Duvida offtopic sobre bootloader

                          Olá, estou com um sério problema...fiz um SO -simples com umas 10 funçoes... parecido com o mikeOS...
                          Então depois de muito esforço e mais de 1500 linhas de programaçao(sim... é pouco...)
                          Decidi transformar os arquivos em .img...
                          100% rodando perfeitamente no pc...
                          Porém queria mais... queria transforma-lo em .ISO pois o mikeOS funciona em ISO...
                          Transformei em ISO e iniciei com uma maquina virutal... a principio funcionou o loader porém ele não conseguiu encontrar o kernel... ou seja, segundo o loader, houve falha no "sector 02" ou seja no setor 2, então pensei que meu loader era feito para disquetes e não para ISO's... alguma ajuda?

                          Segments do kernel iniciados pelo loader são 0800:0000
                          Alguma dica?
                          Valeu e forte abraço!

                          Comment


                          • Font Size
                            #14
                            muito bem explicado, vlw por compartilhar, hoje em dia é díficil achar material na net bom assim...vlw

                            Comment


                            • Font Size
                              #15
                              Bom, resolvi copiar e salvar em um arquivo ".doc".

                              Link: Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...

                              Tem dois arquivos um ".doc" e outro ".odt" um é para windows e o ".odt" para linux.

                              Coloquei um curso de assembly para complementa, encontrado no Guia do Hacker.

                              Bons estudos.

                              Comment

                              X
                              Working...
                              X