Академический Документы
Профессиональный Документы
Культура Документы
Assembly não é difícil, pelo contrário, é, de longe, a linguagem mais simples existente.
Poucos comandos são necessários para programar em Assembly, diferente de dezenas de funções,
classes, API e opções existentes nos frameworks das linguagens de alto nível.
Para entender melhor, vamos começar de cima, de onde você provavelmente deve estar agora, ao ler
esse tutorial de Assembly.
Para o usuário, é tudo a mesma coisa, não importa se ele esteja no Windows, MacOS, Linux,
Android ou TV Digital: ele quer ver menus, botões, clicar, arrastar, fechar e o mesmo de sempre.
Uma mera tela preta, como a do MS-DOS ou Terminal do Linux, já seria motivo de espanto e
repúdio. Nesse estágio, as coisas são voltadas para o agrado desse tipo de usuário, que mesmo sendo
totalmente leigos, são os que sustentam o ramo da computação.
E realmente, a grande maioria das pessoas não tem motivos para entender o que se passa por
debaixo dos panos dessas aplicações: são médicos, advogados, professores exibindo slides nas aulas,
caixas de supermercado e praticamente todo tipo de profissional vai ter contato com essa camada.
Para fazer programas desse tipo, de alto nível, usamos linguagens de programação de alto nível,
como Java, linguagem C, C++, C#, Python, Pascal, Delphi, Visual Basic, JavaScript, PHP e outras
linguagens famosas.
Os programados dessas linguagens são capazes de criar entender como funcionam os softwares de
alto nível em um nível não muito profundo, pois não é necessário entender muito do funcionamento
dos sistemas operacionais.
Na linguagem de programação Java, por exemplo, você nem precisa se importar com o sistema, pois
é uma linguagem multi-plataforma, ou seja, uma aplicação feita em Java pode rodar em Windows,
Linux, Mac, celulares etc, com poucas ou nenhuma alterações.
Isso porque os comandos e códigos que vamos usar na linguagem Assembly são diferentes e
específicos para cada tipo de processador. Ou seja, o nível de abstração da camada da linguagem
Assembly é dependente do sistema.
É tão dependente que até precisamos saber como é organizada e o funcionamento da memória da
máquina onde vamos programar.
Por isso não existem cursos para todos os tipos de Assembly, a linguagem varia de acordo com cada
máquina. Diferente da linguagem Java ou C++, que não importa o tipo de computador para
programar.
Por estar abaixo das aplicações gráficas, das linguagens que criam essas aplicações e ser dependendo
do sistema, a linguagem de programação Assembly é dita de baixo nível.
A camada do código de máquina
Você já deve ter ouvido falar que tudo, absolutamente tudo, em computação, é feito de números 1 e
0. E isso é verdade.
O computador (no sentido bem baixo da palavra, ou seja, o metal, as peças eletrônicas) só entende e
obedece a esses comandos, que nada mais são que uma série de números binários (1’s e 0’s). Porém,
quantas vezes você já programou ou ouviu falar de alguém que programa em binário?
Esse é o limite dos programadores. Porém, há muito, mas muito mais abaixo do Assembly, que
envolvem coisas de elétrica e eletrônica digital (latches, flip-flops, transistores, circuitos integrados
etc). Quem se interessar por esse meio, poderá adquirir conhecimentos através de cursos como
Engenharia de Computação, Engenharia Elétrica, Engenharia Eletrônica e cursos do gênero.
Embora a tecnologia tenha avançado bastante, os conjuntos de instruções não mudaram a ponto de
ser necessário um novo aprendizado. Embora os primeiros microprocessadores da Intel de 32 bits,
tenham quase 30 anos, seu ‘jeitão’ continua o mesmo, e amplamente usado.
O que vêm mudando é capacidade e velocidade de processamento dos mesmos.
Esse tipo de arquitetura também foi implementada em processadores da AMD, por exemplo.
Esses conjuntos de instruções de diversos processadores diferentes obedecem a um conjunto de
instruções da mesma arquitetura, que são conhecidos como x86-32, i386 ou simplesmente x86
(subtende-se que se trata de 32 bits, pois os processadores de 16 bits estão em desuso).
Por isso, é comum trabalharmos com números hexadecimais em Assembly (base numérica de 16
elementos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E e F). Porém, embora ajude bastante, ainda é algo
extremamente enfadonho.
Para superar essas barreiras, a linguagem de Assembly possui palavras reservados chamada
mnemônicos, que servem para o humano programar com maior facilidade, sem ter que usar números
o tempo inteiro.
Por exemplo, até mesmo linguagem C podemos trabalhar com endereços de memória.
Mas endereços são números (e geralmente grandes), então para evitar decorar e escrever números,
damos nomes as nossas variáveis e passamos a tratar elas por esse nome, e não pelo seu endereço.
Então, o mnemônico é um nome que usamos para substituir diversos comandos, é como se fosse um
atalho: estamos escrevendo com nomes diferentes, mas a ação é a mesma, pois é mais fácil tratar
uma pessoa pelo seu nome do que com seu número do RG.
Mas existe uma diferença entre o Assembly e as demais linguagens: em Assembly, tudo é binário,
inclusive as operações com os dados.
Podemos somar um número a outro usando apenas números binários que representam as etapas da
soma. Obviamente isso é extremamente trabalhoso, e vamos usar o mnemônico add ao invés de
números, para tratar operações de adição.
Por exemplo, a instrução hexadecimal dessa operação é: 83060F000A
Ou seja, com os mnemônicos vamos dar nomes as operações, dados e instruções, ao invés de
trabalhar com os opcodes, que são instruções diretas de máquinas.
Existem diversos tipos de Assemblers no mercado, mas vamos usar o NASM (Netwide Assembler),
pois ele é gratuito, atualizado e está disponível tanto para as plataformas Linux como para Windows.
Para mais informações sobre como baixar o NASM, acesse seu site oficial e instale o NASM para
seu sistema, para que possa prosseguir com nosso curso de Assembly: http://www.nasm.us/
Já um carro é bem mais barato e não é tão caro pra manter quanto um avião.
Mas é bem mais lento, perigoso e menos eficiente.
Mas é fácil de dirigir um, e não precisa de muito estudo, apenas temos que tirar a carteira de
habilitação.
Ora, se é mais barato e prático, devemos usar carros para viajar? Depende da viagem.
Já uma bicicleta é bem, mas bem, mais barata. Não precisa gastar dinheiro para usá-la, nem é
necessário ter uma idade mínima, habilitação ou sequer idade mínima para se deslocar numa bike.
Ora, se é praticamente de graça viajar em uma bicicleta, devemos usá-la para viajar?
Depende da viagem.
Tenho certeza que você entendeu os dependes dos exemplos anteriores, bem como tem bom senso
suficiente para saber quando usar um ou outro.
Para viagens longas entre lugares distantes, avião sem dúvidas é a melhor opção.
Para ir a outra cidade, ou viajar para o interior ou literal, é mais cômodo ir de carro.
Já para ir pra escola ou andar alguns quarteirões, a bicicleta é a melhor alternativa.
Com esse exemplo, é bem fácil entender, mas geralmente as pessoas não levam isso para o mundo da
programação, e nesse âmbito a situação é a mesma: você tem que ver seu problema e analisar qual a
melhor solução para ele
.No caso, qual melhor linguagem, tecnologia e o melhor meio para abordar tal problema.
Portanto, dizer que linguagem A ou B é melhor, é dar um atestado de sua ignorância e estará
carimbando seu documento de leigo poser.
Porém, a linguagem Assembly é bastante respeitada e considerada por muitos como a melhor,
principalmente por engenheiros, escovadores de bits (pessoas que amam computação, e querem
saber tudo que ocorre, nos mínimos detalhes, em suas máquinas) e por hackers.
No próximo artigo de Assembly entraremos em detalhes sobre as vantagens dessa linguagem, bem
como suas desvantagens.
Sim, como todas as linguagens, há desvantagens em usar o Assembly. Não se iluda.
Essa é uma das grandes vantagens de programação voltadas para web, como PHP, JavaScript e a
linguagem de marcação HTML, elas só dependem do navegador, não dependem do sistema
operacional, muito menos de um tipo específico de processador, como precisa as variáveis do
Assembly.
As vezes deixamos de lado uma linguagem poderosa e eficiente (como Assembly, C ou C++) e
optamos por uma mais lenta e menos poderosa, como Java ou C# simplesmente porque precisamos
ser produtivos, ou seja, precisamos produzir mais em menos tempo.
Uma aplicação que você faz em algumas horas em Java, Python ou Perl, levaria semanas ou meses
para fazer em Assembly. Os códigos em Assembly são longos, cheios de detalhes e pormenores, o
programador fica a cargo de tudo.
Já em Assembly as coisas não vêm prontas, não há uma infinidade de bibliotecas, funções e recursos
feitos e prontos do jeito, e do tanto, que as linguagens de alto nível. Logo, é necessário criar mais
códigos e programas para fazer algo nessa linguagem.
Assembly é eficiente
Se você mandar duas pessoas, equipes ou empresas, fazerem os mesmos softwares, verá que é
impossível o código delas serem iguais. Programar é raciocinar, é criatividade, depende do intelecto,
experiência e raciocínio dos programadores e chefes.
É por isso que existem navegadores Web bons e ruins, Sistemas Operacionais lentos e rápidos, jogos
bem feitos e mal feitos etc.
Isso tudo é eficiência: fazer um programa que rode mais rápido, que consuma pouco processamento
ou que exija o mínimo de memória possível. E isso o Assembly é único.
Um programa bem feito em Assembly é simplesmente imbatível.
Sim, é trabalhoso.
Sim, é demorado.
Sim, é, algumas vezes, entediante. Mas uma vez feito, e bem feito, você terá feito um ótimo trabalho
e poderá ter a certeza que vai tirar o máximo de sua máquina.
Não é à toa que é Assembly é uma linguagem muito usada em situações críticas, como em alguns
trechos da construção de sistemas operacionais, como o Linux (em sua grande parte é feito em C,
mas em algumas partes é necessário usar Assembly).
Assembly é rápido
O gerenciamento de memória na linguagem Java, por exemplo, é feito de forma automática.
A vantagem disso é que o programador não precisa lidar com ponteiros, endereços de memória,
alocação e liberação de memória (o que é considerado por muitos como as coisas mais difíceis em
programação).
A desvantagem é que isso não é perfeito, e não passa nem perto de ser algo 100% eficiente.
Em Assembly não existe nada automático assim, é você programador que vai mandar e controlar
tudo. E isso é essencial, ter o controle de tudo, quando é necessário funcionamento máximo, como
em microcontroladores e sistemas eletrônicos (imagina um sistema lento em uma aeronave? Não dá,
em questões e sistemas de segurança, precisamos de processamento máximo).
“Com tantos computadores poderosos de gigas e gigas de memória e processamento, por quê se
preocupar com o tanto de memória utilizada?” pode se perguntar o leitor e programador de
linguagens de alto nível.
Do ponto de vista prático, nenhum empresário vai gastar Megas de memória em simples circuitos,
como de calculadores, freezer e outros sistemas digitais, quando se pode gastar apenas poucos Kb
usando a linguagem Assembly.
Se assembly usa menos memória, mais barato irá sair o projeto. Isso não é importante, é essencial
para todos os engenheiros.
Ser eficiente só na teoria não adianta, tem que ser eficiente e economicamente viável.
Embora hoje em dia os vídeo-games sejam tão potentes quanto os computadores, eles não são feitos
da mesma maneira que os PC's e Notebooks. Eles não tem as mesmas peças, acessórios e recursos
que facilitam a programação neles.
Ou seja, em alguns casos, SÓ É POSSÍVEL DE SE TRABALHAR COM ASSEMBLY.
Em décadas passadas, não só o hardware dos vídeo games eram controlador por mas os jogos eram
feitos inteiramente com o uso da linguagem Assembly.
Isso se deve ao fato do programa em Assembly ser muito eficiente e consumir pouca memória.
Além de não ter outras aplicações atuando por debaixo dos panos, como acontece em outras
linguagens.
Sistemas feitos em linguagens de alto nível são freqüentemente burlados por hackers, pois as
aplicações que fazem uso de tais linguagens não mostram nem oferecem tudo aos programadores. A
gigantesca maioria desses profissionais não sabe ao que está ocorrendo em baixo nível.
E mesmo que soubessem, a maioria das linguagens simplesmente não oferece a possibilidade de se
trabalhar próximo ao hardware.
Como um aplicativo em Assembly age nos mais baixos e fundamentais níveis, um programa bem
feito nessa linguagem é bem mais seguro em outras linguagens, pois você pode programar e
controlar manualmente cada detalhe do sistema, e de sua máquina.
Ou seja, um bom programador Assembly pode prover segurança e controle que nenhum outro pode
ter. Porém, ele também pode abrir brechas que outras linguagens não abririam.
Fica óbvio o motivo de vários aplicativos de cunho hacker e cracker usarem Assembly.
A definição correta de hacker é daquele indivíduo que quer saber como e porque as coisas
funcionam. Costuma-se chamar escovador de bits aquele que é curioso, tem interesse em saber e
mexer nos computadores em níveis mais fundamentais possíveis.
Não importa se programa em C, Java, .NET ou até mesmo para Web, saber Assembly vai te dar uma
noção de como as coisas realmente funcionam, vai abrir sua mente, melhorar seu raciocínio e
compreensão sobre computadores e dispositivos digitais, deixando você, por natureza, diferenciado
dos outros profissionais que simplesmente usam as tecnologias, sem saber o que está ocorrendo
debaixo de seu nariz.
“Não sou louco em querer entender como funciona um carro. Louco é quem senta em cima de
toneladas de ferro que possuem a força de centenas de cavalos, sem saber o que está acontecendo
logo abaixo.”
Como programar em Assembly no Windows – Instalando o
Assembler NASM
Para começarmos a programar na linguagem de programação Assembly, precisamos de um
programando chamado Assembler, que irá converter nosso código para um código que a máquina irá
entender.
Vamos usar o NASM (NetWide Assembler), que pode ser usado no Windows ou no Linux.
Nesse tutorial de nosso curso de Assembly, vamos ensinar como instalar esse Assembler no sistema
operacional Windows.
Diferente do que os usuários de Windows devem estar acostumados, a utilização desse programa se
dará pelo terminal de comando, o MS-DOS (sim, aquela tela preta).
Baixando o NASM
Para baixar o NASM vá na página oficial do Netwide Assembler:
http://www.nasm.us
Como o projeto continua se desenvolvendo, não podemos especificar uma versão, pois no momento
que você estiver lendo esse tutorial de Assembly a versão oficial do NASM pode ser diferente da
versão usada pelo Assembly Progressivo.
No arquivo zipado, você deve descompactar o arquivo e colocar o nasm.exe e outros arquivos/pasta
no diretório de seu sistema (geralmente é a pasta C:\Windows\System32), pois o NASM precisa
estar no path do DOS (digite path no cmd.exe e veja seu path).
Para checar se você instalou corretamente o NASM, vá no menu iniciar e digite cmd, e abra o
cmd.exe.
Uma tela do MS-DOS deverá abrir. Digite o seguinte comando:
nasm –h
Vamos usar o NASM (NetWide Assembler), que pode ser usado no Windows ou no Linux.
Nesse tutorial de nosso curso de Assembly, vamos ensinar como instalar esse Assembler no sistema
operacional Linux.
Para programar em Assembly, iremos usar corriqueiramente o terminal do Linux, tanto na instalação
como na montagem de nossos códigos-fonte, para criar os programas.
Baixando o NASM
Para baixar o NASM vá na página oficial do Netwide Assembler:
http://www.nasm.us
Como o projeto continua se desenvolvendo, não podemos especificar uma versão, pois no momento
que você estiver lendo esse tutorial de Assembly a versão oficial do NASM pode ser diferente da
versão usada pelo Assembly Progressivo.
Já dentro do diretório linux/ você encontrará os arquivos rpm para instalar em distribuições Linux do
tipo Red Hat, como o Fedora.
Após baixar e descompactar, pelo Terminal vá na pasta do NASM e rode o script para configurar a
instalação, com o seguinte comando:
./configure
PS: caso ocorra erros em sua instalação, efetue-a como super usuário, ou através do comando sudo
antes de cada comando.
Não se assuste, em breve você entenderá tudo perfeitamente e dominará esse bela e poderosa
linguagem de programação.
section .data
msg db 'Como programar em Assembly - Curso Assembly
Progressivo', 0AH
len equ $-msg
section .text
global _start
_start: mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 80h
mov ebx, 0
mov eax, 1
int 80h
Sim, todas essas linhas de código são para exibir a mensagem "Como programar em Assembly -
Curso Assembly Progressivo".
Esse, porém é um código 'humano', pois usamos mnemônicos, que são símbolos e códigos para que
nós possamos entender.
Obviamente, os computadores não leem como as pessoas, eles simplesmente obedece aos comandos
em binários.
E é isso que vamos ensinar no próximo tutorial, sobre como criar os object files (código objeto) e
linkar arquivos em Assembly, nós vamos ensinar como transformar esse código humano em código
binário.
Vamos montar (e não compilar) tal código, que é o que seu computador realmente vai entender e
obedecer.
O código de máquina será o código objeto, que são arquivos com extensão .o
Em seguida, o próximo passo é reunir todos esses object files, bem como códigos que usamos de
outras bibliotecas, e criar um executável. Ou seja, vamos linkar, agrupar tudo que é necessário para
rodar o programa.
32 ou 64 bits:
ld hello.o -o hello
Pronto, agora você tem seu arquivo executável "hello". Para rodá-lo, digite o comando a seguir, que
deve mostrar uma mensagem na tela:
./hello
---------------------------------------------------------------------------------------------
Uma outra maneira de fazer todo esse processo é a seguinte:
1. Criar o código-objeto:
nasm -f hello.asm
2. Linkando
32 bits:
ld hello.o -o hello
64 bits:
ld -m elf_i386 hello.o -o hello
Sim, programar em Assembly é escrever bastante, pois é uma linguagem totalmente crua, onde muito
pouco 'existe' e muito, quase tudo, é necessário criar.
Para se fazer um simples programa de cálculos matemáticos simples (somar, subtrair etc) é
necessário que fazer uma rotina, manualmente, para essa tarefa, usando somente as instruções
nativas do processador.
Visando essa organização, existe um comando (ou simplesmente rótulo, ou marcador) chamado
section, que serve para definirmos seções em nosso código.
Para declarar uma section fazemos:
section .nomeDaSecao
Na .data section, como o nome sugere, é uma região do código que será usada para tratar as
informações, os dados, as variáveis.
Nesse trecho (geralmente o inicial), declaramos e inicializamos as variáveis.
Por fim, a .text section é o local onde irá ficar armazenado suas instruções, que irão trabalhar com
os dados previamente declarados.
Essa é a única seção obrigatória, pois conterá a label (rótulo) _start, que é o local onde os
executáveis são inicializados.
section .dat
;declaração e inicialização de dados
section .bss
;declaração sem inicialização das informações que serão usadas
section .text
;o programa começa a rodar aqui, a partir da _start
Uma prova disso é o sistema operacional Linux, onde sua gigantesca parte é feita em C, com
algumas pitadas em Assembly.
Essa pitada de Assembly no Kernel é justamente na parte que é necessária uma maior eficiência da
máquina, pois como sabemos, em termos de eficiência nenhuma outra linguagem bate nossa amada
linguagem.
Por isso, é bem comum a interação entre Assembly e outras linguagens. Um exemplo disso são os
games de alto desempenho, que possuem rotinas feitas em Assembly, que se comunica com o resto
do programa.
Ainda em nosso curso de Assembly veremos como usar funções das bibliotecas da linguagem C.
Uma maneira de fazer essa interação é através da diretiva (explicaremos o que é isso em breve)
global.
A diretiva global mostra que o label relacionado é global, ou seja, é passível de uso externamente.
Geralmente usamos para declarar o label principal, o _start.
section .dat
;declaração e inicialização de dados
section .bss
;declaração sem inicialização das informações que serão usadas
section .text
global _start
_start:
;o programa começa a rodar aqui, a partir daqui
Neste tutorial de nosso curso Assembly Progressivo, vamos iniciar os nossos estudos das instruções
em Assembly, explicando o que são os labels, labels internos (ou locais), dando exemplos de uso e
mostrando para que servem.
Para criar uma label, basta digitar o nome desse rótulo seguido de dois pontos, ' : '.
Em seguida, escrevemos nossas linhas de código em Assembly.
A sintaxe é a seguinte, então:
label:
;aqui vem o código
;que vai ser nomeado
;de 'label'
Imagine que você criou uma rotina de códigos que tem por objetivo passar um número para outro
registrador, subtrair esse valor daquele e depois substituir o valor original (não importa o que sua
rotina esteja fazendo). Enfim, suponha que você criou um trecho de código que vai repetir várias
vezes durante seu programa em Assembly.
Ou seja, esse código se repete, você vai usar mais de uma vez.
rotinaBase:
;código super
;hiper mega complexo
;que aprendi no
;Assembly Progressivo
Lembrando que a linguagem Assembly está em baixo nível, ela sempre trata tudo em relação aos
endereços na memória.Os labels estão intrinsecamente ligados com endereços de memória.
Um label serve para representar o endereço de um determinado trecho no código (ou para inicializar
variáveis e constantes que podem ter seus endereços realocados).
Assim, se usarmos esse trecho de código várias vezes, em vez de repeti-lo basta voltar ao ponto
(endereço) na memória que tem esses códigos.
Porém, é complicado para os humanos tratarem os endereços de memórias como números (em
binário, hexadecimal ou mesmo decimal), por isso damos um nome a esse endereço de memória, um
rótulo, e passamos a chamar esse local da memória pelo seu label. Bem mais simples, não?
No nosso código do Hello World em Assembly, usamos o label '_start', que serve para definir para o
NASM onde vai começar nosso programa.
Como outro exemplo do uso de label em nossos códigos Assembly, vamos supor que durante a
execução de um programa seja necessário incrementar uma variável 'numero' várias vezes.
incrementa:
inc numero ;incrementa 'numero' em uma unidade
O NASM, que é o Assembler que estamos usando em nosso Curso de Assembly, permite a definição
de labels locais.
Para isso, basta colocar um ponto, ' . ', antes do nome da label.
Por exemplo, uma representação de um código que duas labels internas, de mesmo nome, mas em
locais diferentes, que fazem a mesma coisa (incrementar), mas incrementam variáveis diferentes:
trecho1:
;trecho 1 do código
.incrementa:
inc numero1
;continuação trecho 1
trecho2:
;trecho 2 do código
.incrementa:
inc numero2
;continuação do trecho 2
Note que uma label local se refere a label 'geral', imediatamente superior.
Cuidado para não se confundir.
Nossos estudos sobre labels não param por aqui, mas você já aprendeu uma ótima noção sobre os
rótulos, embora ainda falte coisas importantes, como o ret, que é uma instrução de retorno, que
serve para definir onde termina um rótulo/label.
Ao decorrer de nossa apostila online de Assembly usaremos bastante labels, então você aprenderá
mais sobre elas vendo exemplos reais de código.
Se estudou linguagens como C ou Java, você alocava espaço na memória ao declarar variáveis e
estruturas (em C é possível ainda, a alocação dinâmica de memória).
Nesse tutorial de nosso curso de Assembly, vamos aprender como reservar espaço em disco em
Assembly, ver quais as diferenças e peculiaridades nessa linguagem de baixo nível.
Alocação de memória em programação
Em outras linguagens de programação, para declarar variáveis precisávamos definir o tipo antes.
Por exemplo, em C ou C++, escrevíamos 'int' para inteiros, 'float' ou 'double' para decimais, 'char'
para caracteres, dentre outros tipos.
Ao fazermos isso, sem saber (diferente do Assembly, em que vemos claramente como as coisas são
feitas), estamos dizendo muito mais do que simplesmente a alocação de memória em si.
O resultado de uma operação entre um inteiro e um decimal não é totalmente previsível, depende da
variável em que vamos armazenar, da linguagem e de outras regra específicas.
Quando declaramos uma variável do tipo double ou float, já fica subentendido que haverá uma
vírgula (ou ponto), representado sua parte decimal. Além disso, há divisões no espaço alocado de
memória, para armazenar a parte decimal e a parte não decimal.
Enfim, acontece muito mais do que simplesmente reservar um espaço de memória. Muitas rotinas
úteis, que facilitam a vida de programador acontecem por debaixo dos panos.
Por exemplo, usamos o mnemônico ADD para adicionar um número a outro. Mas ele não vai
simplesmente adicionar todos e quais números automaticamente como costumamos fazer em outras
linguagens.
Se o resultado der mais de dois dígitos, por exemplo, você terá que fazer uma rotina para exibir
esses dois dígitos (sabe quando você soma no papel, fazendo continha e o valor da soma dá mais que
9, aí 'vai 1' ou 'sobe 1' ? é algo parecido) ; ao somar, ter cuidado para saber se somou o caractere '1'
ou realmente o número 1. Case seja caractere, ou queira exibir, terá que fazer alterações, e por aí vai.
Vamos usar as seguintes variações da diretiva define: DB, DW, DD, DQ e DT.
Eles significam e alocam determinados número de bytes, veja:
Sabendo disso, poderemos agora mostrar como é a sintaxe de uma instrução em Assembly para
alocar memória:
Nome_da_Variavel diretiva_define valor
Colocamos a letra H ao final do número para dizer que estamos representando em Hexadecimal.
Se fossemos colocar em binário, temos que colocar a letra B ao final:
letra1 DB 01000001B
Para saber mais sobre os caracteres em programação, consulte nosso artigo do site C Progressivo,
que também mostra a tabela ASCII:
http://www.cprogressivo.net/2012/12/O-tipo-char-como-escrever-textos-na-linguagem-C.html
Um pouco de matemática
Em Assembly, trabalhamos sempre com bytes, que equivale a 8 bites.
Cada bit desse pode 0 ou 1, então podemos representar até: 2^8 = 256 caracteres com um byte.
Em Hexadecimal, podemos representar esses 256 caracteres usando os números 00H até FFH.
Ou seja, 41H caberia em um byte, pois é menor que FFH.
Agora 2112H só caberia em dois bytes, onde um armazenaríamos o byte 12H e no outro o byte 21H.
Vamos armazenar uma senha na variável 'senha', ela conterá 4 dígitos decimais: 1234
Esse número, em hexadecimal equivale 4660H.
Precisamos, então, definir dois bytes, ou uma palavra (word). Um byte armazena o 60H e o outro
armazena o 46H.
Para alocar memória para essa senha, faríamos:
senha DW 466H
E sempre que usarmos a variável curso, o Assembly saberá que se trata de conjunto de caracteres.
Porém, esse exemplo, assim como o anterior, tem mais caráter de informação para você, leitor de
nosso curso Assembly Progressivo.
A maneira mais prática e utilizada para armazenar uma string, é utilizando a define DB e escrevendo
a string.
O Assembly irá alocar, automaticamente, todos os caracteres, como se tivéssemos feito o exemplo
passado.
No exemplo do "Hello, wolrd" em Assembly, nosso primeiro programa, fizemos isso:
helloWorld DB 'Curso Assembly Progressivo: online, gratis e completo'
Para reservar memória, usamos a diretiva RES, ao mesmo molde da diretiva DEFINE:
RESB Reserve Byte -> reserva 1 byte
RESW Reserve Word -> reserva 2 bytes
RESD Reserve Doubleword -> reserva 4 bytes
RESQ Reserve Quadword -> reserva 8 bytes
REST Reserve Ten -> reserva 10 bytes
Por exemplo:
variavel1 RESB 1 ; nesse caso, reservamos apenas 1 byte
variavel2 RESB 2 ; aqui, reservamos 2 bytes
variavel3 RESW 3 ; 3 palavras são reservadas, o que nos dá 3*2 = 6 bytes
variavel4 REST 10 ; reservamos 10 unidades, de 10 bytes cada
Lembramos que vetores e arrays em Assembly são um vasto conteúdo, há uma série de
possibilidades e conceitos por trás desta ideia, e ainda veremos muito sobre o assunto em nosso
curso.
Porém, este tutorial está na seção básica e se destina a apresentar as ideias iniciais, alocação e
inicialização de elementos de um vetor.
Naquele artigo mostramos como declarar variáveis, dando um nome para elas e definindo o tanto de
bytes que iremos separar em memória somente para aquelas variáveis, através de comandos como
DB e DW.
E é claro que você não vai manusear cada byte desses (embora programadores Assembly sejam
conhecidos por serem escovadores de bits), e é para isso que existem os arrays, também conhecidos
por vetores.
Um vetor, ou array, nada mais é que um bloco enorme de bytes, onde cada bloco é usado como uma
variável, digamos assim, pois trabalhamos diretamente com bytes de memória, não importa se seja
pra um inteiro, caractere ou booleano, pois essas ideias são de linguagens de alto nível, que abstraem
diversos conceitos do que realmente ocorre por debaixo dos panos.
Para nós, vetor ou array em Assembly é um bloco de bytes, geralmente grande, para que possamos
manipular uma quantidade maior de informações de uma maneira bem mais simples, óbvia e lógica.
No decorrer de nosso curso nos depararemos diversas vezes com arrays.
Para alocar um bloco de vários bytes ainda utilizaremos a define, mas precisamos dizer quantas
vezes esta alocação deve ocorrer.
Para dizermos o tanto de vezes (de blocos de bytes) que queremos alocar, vamos usar a diretiva
TIMES (que pode ser traduzida como vezes . 3 times -> 3 vezes, 4 times-> 4 vezes).
Em seguida, devemos dizer o número de vezes que a define vai se repetir.
Após nomear, usar a TIMES, dizer o tanto de vezes que a alocação de bytes deve ser feita, devemos
obviamente dizer quantos bytes vão ser alocados por vez.
E como sabemos, para alocar bytes usamos os comandos DB, DW, DD, DQ e DT.
E por fim, devemos dar um valor inicial para esses bytes do bloco de memória.
Você pode alocar 1 milhão de blocos de DT (cada DT aloca 10 bytes), e inicializar cada um deles
com um valor numérico, de forma totalmente automática.
Vamos criar um array de nome "vetor", cada elemento do vetor vai ser alocado através de um DB,
esse vetor terá 10 elementos (então vamos repetir 10 vezes a alocação DB) e vamos inicializar todos
os elementos de nosso array com valor 0:
vetor TIMES 10 DB 0
Agora vamos declarar um vetor de nome "array", ele será composto de 20 elementos do tipo word (2
bytes cada), e será inicializado com o valor hexadecimal FFH:
array TIMES 20 DW FFH
Por exemplo, vamos supor que nossa variável "elemento1' ocupe um byte, vamos dizer que na
posição "x" de memória:
elemento1 DB 00H
Se formos, em seguida, alocar a variável "elemento2" que é do tipo e word e ocupa 2 bytes, ela vai
estar na posição "x+1" de memória, pois na posição "x" está o "elemento1" e ele ocupa 1 byte:
A próxima variável que declararmos vai estar na posição "x+3", pois o local "x" é ocupado por
"elemento1" e os dois bytes seguintes é ocupado por "elemento2", concorda?
Note que que o "vetor1" ocupa 10x1=10 bytes, pois ele aloca 10 elementos do tipo byte (DB).
E como dissemos, o "vetor1" vai inicial no local de memória "x+3", como ele ocupa 10 bytes, o
próximo vetor vai se iniciar na posição "x+3+10", ou seja, "vetor2" começa na posição "x+13", ok?
Agora vamos analisar "vetor2", ele declara um bloco de memória de 20 elementos do tipo WORD,
onde cada um destes ocupada 2 bytes. Então "vetor2" ocupada 20x2=40 bytes.
Entendeu mesmo?
Então em que posição de memória vai estar localizada a variável "elemento3"?
A resposta está em branco ao lado (seleciona o local com o mouse): x+13+40 = x+53
E caso deseje declarar outra variável abaixo de "elemento3", em que posição de memória esta
variável vai começar? (lembre-se que "elemento3" ocupa 4 bytes): x+