Ir para conteúdo
Faça parte da equipe! (2024) ×
Conheça nossa Beta Zone! Novas áreas a caminho! ×
  • Quem está por aqui   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.

Aprendendo Assembly


AceStryker
 Compartilhar

Posts Recomendados

Porque Assembly?

Assembly é uma linguagem de baixo nível, ou seja, é uma linguagem próxima daquela que as máquinas "entendem". Para utilizá-la é necessário conhecer não só a própria linguagem como também as características de funcionamento da máquina. Isto é coisa de doido? Nem tanto. Vou fazer algumas comparações e depois você pode decidir se vale a pena assemblar.

 

Arquivos executáveis de alta performance

Se você tem uma rotina que acaba fritando a CPU de tanto processamento, então pense no Assembly. Os executáveis criados em Assembly apresentam duas grandes vantagens: velocidade de execução e tamanho reduzido. Além disto, como a linguagem não tem firulas e vai direto ao ponto (ou aos registradores ), a execução exige muito menos recursos porque qualquer assembler supera a capacidade dos melhores compiladores de linguagens de alto nível. O software de performance crítica é um alvo natural para os programas em assembly puro.

 

Bibliotecas de link dinâmico (DLLs)

O MASM (da micro$oft), NASM (da equipe liderada por Simon Tatham e Julian Hall), o TASM da Borland, o A386 de Eric Isaacson ou o GoAsm de Jeremy Gordon, enfim, praticamente todos os assemblers mais conhecidos são capazes de construir bibliotecas de link dinâmico de altíssima performance que podem ser utilizadas pelos próprios programas assembladores, pelo Visual C/C++, Delphi, Visual Basic, e outras linguagens capazes de chamar uma DLL. Usar um assembler significa obter arquivos de tamanho mínimo e alto rendimento que podem ser interfaceados com qualquer linguagem apta a chamar uma DLL. Algoritmos que, por exigirem processamento pesado, não podem ser implementados em linguagens de alto nível, tornam-se viáveis quando escritos em Assembly.

 

Módulos de biblioteca para programas Visual C/C++

O MASM produz um formato de módulo objeto idêntico aos compiladores do Visual C/C++. Isto permite construir módulos ou bibliotecas em MASM e linká-los diretamente a programas C/C++. Com isto, programadores C/C++ podem manipular áreas de código críticas de forma muito eficiente, ou seja, podem otimizar a manipulação de gráficos, dados de alta velocidade, criptografia, compressão de dados e qualquer outra forma de manipulação de informação que exija muito processamento.

 

Software Gratuito

Assembladores são softwares gratuitos, não podem ser comprados, vendidos ou incluídos em qualquer tipo de software comercial. Já que o MASM é uma das poucas coisas que a Microsoft disponibiliza sem cobrar um caminhão de US$... este é mais um motivo para começar a assemblar.

Para mim, estes quatro argumentos são mais do que suficientes. Aliás, sempre que posso e quando o peso do processamento é muito grande, opto pelo Assembly. É claro que não vou criar um aplicativo inteiro nesta linguagem, mesmo porque é para ganhar tempo na produção que existem os RAD da vida, mas enxertar código Assembly no Delphi ou no C++ são dois palitos. E o resultado é altamente compensador!

 

Na série de tutoriais desta seção vou tratar apenas de Assembly puro (nada de mistura com outras linguagens) porque se eu misturar assuntos o resultado acaba sendo uma salada. Uma vez dominado o arroz com feijão da linguagem, criar estas entidades híbridas não é nenhum bicho de sete cabeças. E aí, está afim de me acompanhar? Então vamos lá... siga a vovó.

 

Por Onde Começar?

 

Assemble vem do Inglês e significa construir, juntar partes; é daí que vem o nome de uma linguagem de programação, o ASSEMBLY. Assembler significa construtor e é o nome que se dá a programas que "juntam partes", que "constroem" executáveis. É por isto que não é possível escrever um programa em assembler (como se costuma ver por aí): o programa é escrito em Assembly e depois pode ser transformado num executável por um assembler

 

Por onde começar é aquela parte inicial, chata pra caramba, mas que não adianta ignorar porque vai fazer falta mais tarde. Neste texto você vai ter a oportunidade de conhecer um pouco do MASM e da estrutura de um programa.

 

Para se comunicar com um assembler são utilizadas algumas convenções que o programa exige para poder executar as tarefas desejadas. Cada assembler tem suas próprias convenções. Nestes tutoriais vamos utilizar o MASM32 como assembler, mas você pode usar qualquer outro da sua escolha. As diferenças são pequenas e é fácil adaptar o código.

 

O Assembler

 

Antes de mais nada, faça o download do macroassembler da Microsoft, o MASM 32 versão 9, na seção de downloads da Aldeia. Procure na categoria Informática|Compiladores/Decompiladores. Descompacte o arquivo zipado num diretório (quem "fala" Assembly não usa pastas, usa diretórios!) da sua escolha e clique em /seuDiretório/QEDITOR.EXE. Esta é a interface de edição de programação - não é cheia de nove horas porque programadores assembly estão acostumados a escovar bits e a fazer a maior parte do trabalho na unha sem muita frescura.

 

Muito bem. O editor está à disposição e aí vem a pergunta: o que fazer agora? tô afim de começar! Hehehe... lembra da parte inicial, chata pra caramba? Pois é esta aqui. Tenha um pouco de paciência e, por enquanto, feche o editor e leia o resto do texto. Depois a gente conversa.

 

A sequência do trabalho

 

Quando se escreve um programa, na realidade se escreve um texto que contém um roteiro que precisa ser transformado num programa. Esta transformação é feita em duas etapas. Primeiro, o texto precisa ser transformado num novo roteiro que contenha instruções para a CPU. Esta primeira tradução produz os assim chamados arquivos objeto. O programa que produz arquivos objeto é chamado de assembler ou compilador. Os arquivos objeto, por sua vez, servem de fonte para outro tipo de programa: o linker. Os linkers adicionam referências de endereços aos arquivos objeto e os transformam em arquivos executáveis, a versão final do seu programa. Resumindo as etapas, tem-se o seguinte:

 

É necessário se cadastrar para acessar o conteúdo.

 

O MASM é um aplicativo que pode coordenar o seu trabalho: possui um editor de texto, um compilador e um linker. Através da janela do MASM é possível gerenciar todo o processo de produção de um programa.

 

Você pode escrever seu texto (ou script) em qualquer editor de texto, até com o bloco de notas do Windows. Como usaremos o MASM, podemos usar o editor de texto do próprio. Se escrevermos uma receita de bolo no editor de texto e pedirmos para o MASM (compilador+linker) transformá-lo num programa... hmmmm... o MASM vai ficar perdidinho da silva. É preciso criar um texto que o MASM entenda e, o que é mais importante, obedecendo uma determinada estrutura.

 

A Estrutura de um Programa

 

A primeira informação que o MASM precisa para poder trabalhar é o tipo de CPU para a qual o programa se destina. Isto é necessário para que o compilador possa escolher o conjunto de instruções compatíveis com a CPU. Como pretendemos produzir programas de 32 bits, indicamos o conjunto de instruções como sendo do tipo 80386 em diante (80386, 80486, Pentium, etc). Trabalhar com o conjunto de instruções do 386 costuma ser mais do que suficiente. Como é que passamos essa informação para o compilador? Usando uma diretiva apropriada:

É necessário se cadastrar para acessar o conteúdo.

 

Puxa vida, por enquanto, nada de programa. Ainda precisamos indicar qual é o modelo de memória que deve ser usado. Um executável é carregado na memória de acordo com o modelo de memória definido durante a compilação. Na época dos computadores de 16 bits, o programa era carregado na memória em segmentos de tamanho predefinido. Era uma complicação danada gerenciar a execução do programa: para cada endereço era necessário indicar o segmento correspondente e saltar de um segmento para outro - parecia soluço e "comia" um monte de processamento. Com o advento dos 32 bits, os executáveis passaram a ser carregados na memória em endereços contíguos. Imagine um segmento único de memória contendo o executável, uma tripa enorme com a sequência de instruções. Este modelo de memória foi denominado FLAT, ou seja, modelo plano ou contínuo. Então, lá vai mais uma diretiva:

 

É necessário se cadastrar para acessar o conteúdo.

 

Qualquer programa, com toda certeza (tem tanta certeza assim?) vai realizar algum trabalho, ou seja, vai ter funções. As funções geralmente precisam de dados para executar uma tarefa. Estes dados podem ser gerados dentro da própria função ou serem enviados para elas. Dados enviados a uma função são chamados de parâmetros. A forma de mandar estes parâmetros também precisa ser definida previamente: se houver mais de um parâmetro, podemos enviá-los de frente para trás ou de trás para frente, ou seja, da esquerda para a direita ou da direita para a esquerda. Veja um exemplo: suponha que uma função espere receber dois parâmetros (param1 e param2). Podemos enviá-los na sequência param1, param2 ou na sequência param2, param1. A primeira convenção de passagem de parâmetros é conhecida como PASCAL e a segunda como convenção C.

 

Os parâmetros recebidos são guardados temporariamente num registrador da CPU chamado de pilha (stack). Imagine a pilha como uma pilha de caixas de sabão em pó no supermercado. À medida que você colocar novas caixas na pilha, a pilha vai crescendo; à medida que tira, a pilha vai encolhendo; se você tirar uma caixa do meio da pilha, as caixas vão cair. Como o conteúdo da pilha é alterado quando uma função é chamada ou quando a própria função alterá-lo, é preciso fazer um ajuste de pilha em cada retorno de função... senão a pilha "cai" e o programa dá pau. Na convenção de passagem de parâmetros do tipo Pascal, a função chamada é a responsável pelo ajuste da pilha antes do retorno. Na convenção C, a rotina chamadora é a responsável.

 

Existe uma terceira convenção de passagem de parâmetros denominada STDCALL (abreviação de STanDard CALL - chamada padrão). Usando esta convenção, os parâmetros são enviados da direita para a esquerda (como na convenção C) mas a função chamada é a responsável pelo ajuste da pilha. A STDCALL é um híbrido das convenções Pascal e C.

 

Os sistemas win32 utilizam exclusivamente a convenção de passagem de parâmetros STDCALL. Podemos e devemos completar a diretiva acima com:

É necessário se cadastrar para acessar o conteúdo.

 

Na maioria das vezes, um programa precisa de dados inicializados (com valores definidos) para poder começar a funcionar. São coisas do tipo nome do aplicativo, título da janela principal, etc. Para indicar ao MASM que vamos listar nomes de variáveis e seus respectivos valores, usamos a diretiva .DATA. Tudo que o compilador encontrar nas linhas subsequentes, até encontrar outra diretiva, ele vai considerar como variáveis (dados) inicializados.

 

Também podemos preparar variáveis não inicializadas, ou seja, fazemos com que o assembler ponha determinados nomes de variáveis na lista de variáveis, mas sem valores definidos. Estes dados não inicializados podem ser usados posteriormente pelo código. A diretiva .DATA? faz a indicação.

 

Variáveis, como o próprio nome indica, podem ter seus valores alterados. Num determinado projeto pode ser que sejam necessários dados de valores fixos, as assim chamadas constantes. Neste caso, utilizamos a diretiva .CONST.

 

Todos estes dados, indicados antes do programa propriamente dito, podem ser usados em qualquer ponto do código. Tanto faz se estamos no módulo principal ou em alguma subrotina (função) - estes dados estão sempre disponíveis e acessíveis. São os chamados dados globais (variáveis e constantes). Enquanto o programa estiver sendo executado, estes dados ficam preservados. Só são destruídos quando o programa termina.

 

Ufa! Finalmente chegamos no miolo do programa. É onde deve ficar o código que indica como nosso programa deve se comportar e o que deve realizar. A diretiva usada não poderia ser outra: .CODE indica o início do nosso código. Só que esta é a última diretiva da estrutura e o assembler não tem como saber onde ela termina. Estabelecemos então o limite com um rótulo seguido por dois pontos. O dá um nome à área de código e indicamos o fim da área com um "end ". Você pode escolher o nome que quiser, por exemplo:

 

É necessário se cadastrar para acessar o conteúdo.

 

Resumindo, a estrutura que o MASM entende e aceita para assemblar e linkar é a seguinte:

 

É necessário se cadastrar para acessar o conteúdo.

 

Criando um Programa

 

Veja quais são os os arquivos envolvidos na rotina de criação de um programa.

 

Para criar um programa escrito em Assembly e que rode no ambiente Windows e *nix, várias etapas precisam ser cumpridas. Inicialmente escreve-se o chamado código fonte ou script do programa e, se necessário, um arquivo de recursos. Estes arquivos, em texto ASCII puro, serão transformados em arquivos objeto os quais, por sua vez, serão utilizados para compor o executável. Observe que são três etapas distintas: elaboração do código fonte, compilação e linkedição.

 

As Etapas

 

É necessário se cadastrar para acessar o conteúdo.

 

Os arquivos de recursos (.**) só são necessários quando se quer utilizar recursos adicionais, como menus e bitmaps. Isto significa que podem ou não estar presentes no seu projeto. Vamos explorar cada uma das fases.

 

O código fonte

 

Os arquivos que contêm o código fonte deve ser gravados em texto ASCII puro, ou seja, não devem conter caracteres especiais de formatação. Podem ser produzidos em qualquer editor de texto que ofereça a possibilidade de salvar arquivos neste formato (geralmente chamado simplesmente de formato texto).

 

O bloco de notas do Windows é um bom editor para este trabalho, mas você pode usar o editor que mais lhe convier, inclusive o editor oficial da Aldeia, o SilicioPad, que nada mais é do que o bloco de notas modificado para mostrar o número das linha no rodapé da janela (como fazer esta mandrakaria será tema de um tutorial avançado). Se quiser experimentar, faça o download do SilicioPad em Downloads/Informática/Editores.

 

É hábito dos programadores indicar a linguagem usada na extensão do arquivo fonte. Por exemplo, .asm para código fonte em Assembly, .c para a linguagem C, .cpp para a C++ ou .pas para Pascal (Delphi). O programa assembler (ou compilador) aceita qualquer extensão, contanto que o código fonte seja o que ele espera.

 

Um arquivo .asm contém as instruções para o processador na forma de palavras e números. Estas instruções serão executadas pelo processador quando o programa rodar. Acontece que o processador não entende o código fonte: ele precisa ser transformado em "linguagem de máquina" e estar "arrumado" de acordo com um padrão que o sistema operacional consiga identificar. Esta transformação é feita em duas etapas: o compilador prepara o código fonte guardando o código fornecido no formato COFF (Common Object File Format) num arquivo objeto (.obj) e este, por sua vez, é transformado pelo linkeditor num arquivo executável (.exe) no formato PE (Portable Executable).

 

O arquivo objeto

 

Um arquivo objeto é criado pelo compilador ou assembler a partir de um arquivo .asm. O compilador pega as instruções do arquivo .asm, que estão em palavras e números, e as transforma no formato objeto COFF, que é o formato que o linker espera. O compilador concatena todo o código e os dados de instrução presentes no código fonte e os coloca em seções de código e de dados no arquivo .obj. A seção de código contém as instruções, os chamados códigos operacionais (opcodes) que o processador executa quando o programa é rodado. A seção de dados contém informações que serão mantidas na memória enquanto o programa estiver sendo executado.

 

Não é possível rodar um arquivo .obj como um programa, por que não tem a forma final de um executável. O formato de um executável esperado pelo Windows é o formato PE. Algumas vezes o arquivo .obj é chamado de arquivo "binário" ou simplesmente "bin", o que se justifica porque ele não contém mais os mnemônicos, apenas números.

 

O código fonte dos recursos

 

Como todo código fonte, este também é um arquivo texto produzido com um editor de texto. Deve conter palavras e números que o sistema operacional usa para montar os recursos do programa que será executado os quais, geralmente, são menus, diálogos e tabelas de strings. Também serve de fonte de referência para outros arquivos como ícones, bitmaps e cursores. Maiores detalhes em como criar um arquivo de recursos você encontra nos tutoriais.

 

O arquivo objeto dos recursos

 

O arquivo de recursos compilado é como se fosse um "arquivo objeto" dos recursos. Normalmente não se usa este termo, mas a comparação é perfeitamente válida. Este arquivo é produzido por um compilador de recursos, o qual formata as instruções contidas num arquivo .** (palavras e números), convertendo-o num arquivo .res pronto para ser inserido na seção de recursos de um executável final por um linker.

 

O executável

 

O arquivo executável é o arquivo final que pode ser executado pelo sistema operacional. Geralmente está no formato PE, reconhecido pelo Unix, Linux, Windows, etc. O programa é produzido por um linker, o qual usa um ou mais arquivos .obj e .res e os combina num executável final. O formato PE também exige que o executável tenha um cabeçalho com informações a respeito do arquivo .exe. O linker fornece estas informações.

 

Arquivos DLL

 

Este tipo de arquivo contém funções e dados que outros executáveis podem utilizar quando estiverem rodando. São úteis quando contêm funções que serão chamadas repetidas vezes por vários executáveis. Ao invés de repetir estas funções em cada um dos executáveis, estes utilizam uma fonte comum: as DLLs. O acrônimo DLL origina-se de Dinamic Link Library - Biblioteca de Vínculo Dinâmico.

 

Códigos Operacionais e Mnemônicos

 

A "linguagem" binária

 

Em nível de hardware só existe um "idioma": o binário. Isto significa que o processador (e todos os outros componentes de um computador) só entendem "binarês", ou seja, bits ligados ou desligados.

 

Digamos que eu queira enviar o valor 1.453.785.342 para um registrador da CPU. Para que o computador "entenda" o que estou querendo dizer, este valor precisa chegar no formato binário. Considerando que bits ligados sejam iguais a 1 e bits desligados sejam iguais a 0, a seguinte "tripa" de bits precisa ser enviada:

 

A Linguagem Assembly

 

Assembly é uma linguagem de programação e uma linguagem de programação serve para fazer programas. Os programas são escritos em forma de texto. Usando um editor de texto criamos o chamado código fonte. Este código fonte é transformado pelo compilador e pelo linker num programa executável.

 

Muitas vezes ouvimos "linguagem assembler". É um erro muito difundido. Na realidade, Assembly é o nome da linguagem e assembler é um programa capaz de compilar código fonte em arquivos objeto.

 

A linguagem Assembly é considerada de baixo nível. Isto não significa que seja menos importante ou eficiente que uma linguagem chamada de alto nível - são apenas modos diferentes de se programar e níveis diferentes de atuação. O que posso dizer é que, com uma linguagem de baixo nível como a Assembly, você pilota diretamente a CPU do seu computador - nada de intermediários.

 

Uma das características da Assembly é que cada linha do código fonte possui apenas uma instrução para o processador (CPU). Por exemplo, MOV EAX,EDX irá MOVer o conteúdo do registrador EDX para o registrador EAX. Neste caso, a instrução "MOV" é chamada de mnemônico. Os mnemônicos são os "apelidos" das instruções, mais fáceis de guardar na memória do que seu valor hexadecimal ou seu valor binário exigido pelo processador. De mnemônico em mnemônico podemos escrever nosso código fonte e fazer com que o processador faça exatamente o que queremos, sem firulas ou perda de tempo. O resultado é um programa enxuto, rápido e altamente eficiente. Tome coragem! Experimente programar em Assembly!

 

Os componentes da linguagem Assembly

 

Os componentes da linguagem Assembly são basicamente as instruções para o processador. Ignorando as instruções que não podem ser utilizadas pelo sistema operacional Windows, assembly condicional, macros, ponto flutuante, MMX e instruções de 64 bits, os componentes da linguagem Assembly podem ser divididos nas seguintes categorias:

 

Instruções de registradores

Instruções de pilha

Instruções de execução

Instruções de memória

Instruções de flag

Declarações de memória

Diretivas para o assembler

Comentários

Instruções para o sistema operacional (Windows)

Instruções de registradores

 

Estas instruções transferem dados ou realizam cálculos utilizando os registradores de 32 bits da CPU. Existem seis registradores de uso geral chamados de EAX, EBX, ECX, EDX, ESI e EDI. Exemplos deste tipo de instrução são:

 

É necessário se cadastrar para acessar o conteúdo.

 

Instruções de pilha

 

A pilha é uma área de memória reservada pelo sistema operacional como área de arquivamento temporário para cada programa que estiver rodando. São exemplos deste tipo de instrução:

 

É necessário se cadastrar para acessar o conteúdo.

 

Instruções de execução

 

Estas instruções desviam o processador para que execute código a partir de um ponto que não seja a próxima linha de execução. São exemplos:

 

É necessário se cadastrar para acessar o conteúdo.

 

Instruções de memória

 

Estas instruções lêem ou escrevem em áreas de memória que não sejam da pilha. Normalmente estas áreas estão na seção de dados do próprio executável ou podem ser alocadas pelo sistema operacional em tempo de execução. São exemplos:

 

É necessário se cadastrar para acessar o conteúdo.

 

Instruções de flag

 

As principais flags usadas são a Z (flag zero), C (flag carry), S (flag de sinal) e D (flag de direção). A maioria das instruções alteram as flags automaticamente para mostrarem o resultado da instrução. Existem determinadas instruções que podem ser usadas para alterar o valor das flags manualmente:

 

É necessário se cadastrar para acessar o conteúdo.

 

Declarações de memória

 

O sistema operacional reserva memória para o executável quando ele é executado. Declarações são feitas para reservar memória na seção de dados ou na seção de constantes se os dados devem ser inicializados, isto é, devem receber um valor. Se forem dados não inicializados, a área de dados pode ficar reservada na seção de dados não inicializados. Isto não toma espaço algum no arquivo executável, por que um espaço de memória é alocado para este tipo de dado quando o executável é iniciado pela primeira vez.

 

Seguem exemplos de como a memória é declarada, o que pode variar de acordo com o assembler utilizado:

 

É necessário se cadastrar para acessar o conteúdo.

 

Diretivas para o assembler

 

São instruções que orientam onde o Assembler deve colocar o código fonte que as segue. O Assembler marca a seção de código como apenas para leitura e executável; as seções de dados definidos e indefinidos como leitura/escrita. Veja alguns exemplos (que podem variar de acordo com o assembler):

 

É necessário se cadastrar para acessar o conteúdo.

Comentários

 

Após ponto e vírgula, o texto é ignorado até a próxima quebra de linha. Desta forma é possível associar descrições e explicações ao código fonte, as quais serão ignoradas pelo assembler.

 

Instruções para o sistema operacional

 

Proporcionam ao programador o acesso a uma grande variedade de funções. No caso do sistema operacional Windows, proporcionam acesso à API. Veja os exemplos abaixo:

 

É necessário se cadastrar para acessar o conteúdo.

 

É necessário se cadastrar para acessar o conteúdo.

Tá na cara que não vai dar para programar desta forma, mesmo por que ninguém é maluco o suficiente para querer transformar opcodes e valores nestas "tripas" ininteligíveis.

 

Valores hexadecimais

 

Ainda em nível de hardware, num processador Intel ou compatível, as instruções estão embutidas nos circuitos e são denominadas de "opcodes" - códigos operacionais. Cada código operacional é identificado por um valor binário. Para realizar uma transferência para o registrador eax, por exemplo, o opcode é 10100001.

 

Apesar da informação poder ser escrita em nível de bit, o tamanho mínimo dos dados e códigos normalmente utilizado é um BYTE (8 bits). Em nível de BYTE, o código pode ser escrito na notação hexadecimal, porém este método de escrever ainda é muito complexo e exige o conhecimento de um grande número de opcodes. Aliás, o opcode 10100001 para transferir um valor para eax é A1 em hexadecimal.

 

Além disto, existe uma dificuldade adicional: os processadores Intel têm a peculiaridade de armazenar os dados em ordem inversa. Por exemplo, se quisermos copiar o valor 56 A7 00 FE para o registrador eax, precisamos enviar este valor como FE 00 A7 56. Só para você saber, esta é a notação hexadecimal do mesmo valor decimal e binário citado acima.

 

Se você não tem idéia do que vem a ser a notação hexadecimal, dê uma chegada na Escolinha da Aldeia e conheça os principais sistemas de notação. Entre eles, você vai conhecer os sistemas binário e hexadecimal

 

Assim não dava para ficar

 

Para facilitar o trabalho de escrever código de baixo nível, há muitos anos atrás foi desenvolvido um sistema onde grupos de códigos operacionais semelhantes receberam nomes que lembram suas funções e que os tornaram muito mais práticos de serem usados. Estes nomes são denominados MNEMÔNICOS. Ficando nos exemplos citados, o opcode 10100001 (em binário), ou A1 (em hexadecimal), foi trocado pelo mnemônico MOV (de mover, transferir). Este é o sistema utilizado nos assemblers de 32 bits modernos.

 

Um mnemônico é um nome reservado de uma família de códigos operacionais que realizam tarefas semelhantes no processador. Os códigos operacionais atuais diferem quanto ao tamanho e ao tipo de operandos que são utilizados. Por exemplo, se quisermos usar o mnemônico MOV, podemos escrever

 

É necessário se cadastrar para acessar o conteúdo.

E viva os mnemônicos!

 

No MASM32, assim como em outros macroassemblers, usamos apenas mnemônicos... graças a Deus! Conversamos usando mnemônicos como MOV, MUL (multiplicar) ou JP (jump=saltar) e deixamos a tarefa da tradução para o "binarês" para o assembler

 

Bit e Binário

 

Bit e Binário, veja o que é possível fazer com um simples bit.

 

Um bit é um elemento elétrico dentro do computador que pode estar "ligado" ou "desligado". Em termos físicos, é um semi-condutor capaz de conduzir pequenas quantidades de eletricidade quando está "ligado", coisa que não consegue quando está "desligado". Quando está "ligado" pode ser considerado como tendo o valor 1 (um). Em linguagem de computador diz-se que o bit está "setado" (do inglês - set). Quando está "desligado", pode ser considerado como tendo o valor zero. Em linguagem de computador o bit está "zerado". Bits só podem estar setados ou zerados - não possuem qualquer outro estado. Portanto, um bit só pode ter um valor binário de 0 ou 1.

 

Dois ou mais bits podem ser associados para criar números maiores. Quando bits são associados, o bit da direita é chamado de menos significativo e, se estiver setado, representa o valor um. O próximo bit, à esquerda, é chamado de mais significativo e possui o fator dois. Quando este bit estiver setado, ele representa o valor dois. Agora imagine um número formado por dois bits. O número em binário pode ser 00 ou 01 ou 10 ou 11 e seus equivalentes no sistema decimal são 0, 1, 2 e 3.

 

Byte, word e dword

 

Bytes, words e dwords são blocos de dados básicos usados em programação. O processador irá trabalhar com o tamanho de dados adequados para executar corretamente as instruções que receber.

 

Um byte possui 8 bits, um word possui 16 bits. Partindo desta premissa, um word possui 2 bytes (16 bits) e um duplo word (dword) possui 4 bytes ou 32 bits.

 

Um byte pode representar valores decimais de 0 a 255. O valor decimal 255 é o total dos valores de todos os 8 bits de um byte, ou seja, decimal 128, 64, 32, 16, 8, 4, 2 e 1. Some estes valores e você vai chegar no valor 255. Isto quer dizer que, quando todos os oito bits do byte estão setados, o valor do byte é 255.

 

Um word pode representar os valores decimais de 0 a 65.535 (o que é o mesmo que dizer 64 Kilobytes). 64 Kb é o total dos valores de todos os 16 bits setados, assim como na explicação anterior.

 

Um dword (literalmente um "double word" ou "palavra dupla") pode representar os valores decimais de 0 a 4.294.967.295 (4 Gigabytes). 4 Gb ou 4 giga é o total dos valores de todos os 32 bits.

 

Existem blocos de dados maiores que o processador consegue manipular - um qword (literalmente "quad word" ou "palavra quádrupla") são 64 bits de dados (4 words ou 8 bytes), um tword possui 80 bits de dados (10 bytes) e algumas instruções podem usar até 128 bits (16 bytes). Dá para perceber que estes números são bastante grandes.

 

Agora vamos para valores menores. Um nibble é a metade de um byte, ou seja, possui quatro bits de dados. Num byte existem dois nibbles e cada um deles só consegue representar valores decimais de 0 a 128. Este valor pode ser representado como um único número hexadecimal. Tome o número hexadecimal 148C como exemplo. Ele é constituído por dois bytes. O primeiro byte contém o valor 14h e o segundo 8Ch. Neste caso, os nibbles contêm os valores 1, 4, 8 e C (em hexadecimal).

 

Depois edito com mais informações...

 

Creditos:

Assembly NumaBoa

Link para o comentário
Compartilhar em outros sites

hehe , muito bom ter trazido para ca..

o EvilCode postou o link neste tópico : http://www.webcheats.com.br/forum/assembly/963375-artigos-e-tutoriais-assembly-e-engenharia-reversa.html

mas como muitos concerteza não irão olhar , auaha :]

Gostei da formatação do topico ficou bem legal...

Abraços *-*

Link para o comentário
Compartilhar em outros sites

Este tópico está impedido de receber novos posts.
 Compartilhar

×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.