Define - Como alocar memória Assembly - RES, como reservar memória

Se você estudou somente linguagens de altíssimo nível, como as de linguagens de script, com certeza nunca se preocupou em alocar memória, pois é tudo feito automaticamente por debaixo dos panos.

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.




Alocação de memória em Assembly - A diretiva define

Obviamente, em Assembly as coisas são um pouco diferente.

Essas coisas que atuam sem o conhecimento do programador simplesmente não existem, e o profissional que programa em Assembly ficará a cargo de tudo.
Em Assembly, você realmente irá alocar espaço em memória. E somente isso.

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.

Como enfatizamos, Assembly é em baixo nível.
Trabalhamos com bits e bytes. E nesse nível, as coisas não vem prontas.
O programador Assembly é que o tem o poder e responsabilidade de absolutamente tudo. Por isso, ao alocar memória, temos que definir o número de bytes que vamos usar.

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:

DB = Define Byte            -> aloca 1 byte
DW = Define Word           -> aloca 2 bytes
DD = Define Doubleword  -> aloca 4 bytes
DQ = Define Quadword    -> aloca  8 bytes
DT = Define Ten              -> aloca 10 bytes

Sabendo disso, poderemos agora mostrar como é a sintaxe de uma instrução em Assembly para alocar memória:
Nome_da_Variavel diretiva_define valor

Por exemplo, para alocar espaço para o caractere 'A', fazemos:
letra1 DB 'A'

Lembramos que, na verdade, embora tenhamos escrito o caractere 'A', tudo são números.
Então, como na tabela ASCII o valor de 'A', em hexadecimal é 41, poderíamos ter feito:
letra1 DB 41H

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, onde um byte equivale a 8 bites.
Cada bit desse pode ser 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 equivalem a 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

Outras maneiras de alocar memória em Assembly
E se quiséssemos alocar uma palavra, como 'curso', por exemplo?
Poderíamos alocar letra por letra:
letra1 DB 'c'
letra2 DB 'u'
letra3 DB 'r'
letra4 DB 's'
letra5 DB 'o'

Porém, seria muito trabalhoso, e há maneira mais fáceis de se fazer isso.
Em vez de ter que dar um nome para cada letra (isso não faz o menor sentido!), poderíamos dar um nome só para o conjunto de letras:
curso DB 'c'
DB 'u'
  DB 'r'
  DB 's'
  DB 'o'

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 uma string (que nada mais é que um texto, um conjunto de caracteres).
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'

Bem mais prático, não?

Reservando memória em Assembly

Até agora, usando a diretiva define e suas variações (DB, DW, DD, DQ e DT), alocamos memória em Assembly para armazenar e INICIALIZAR variáveis! Porém, nem sempre vamos inicializar, apenas queremos alocar.
Isso é comum para armazenar variáveis cujos valores serão fornecidos posteriormente, pelo seu programa, pelo usuário ou um dispositivo de entrada e saída.

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

A sintaxe é um pouco diferente da DEFINE, já que não vamos inicializar.
Assim, em vez de valor inicial, temos que dizer quanto de espaço queremos reservar, dependendo da diretiva que usamos.
Sintaxe para reservar memória:
nome_da_variavel diretiva_res numero_de_unidades

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

Um comentário:

Hilton Dvorak disse...

Excelente blog sobre Assembly ! Sou autodidata (deixo claro que não quero dizer que sou bom... ainda), mas venho estudando há anos c e assembly e o conteúdo aqui é muito excelente !
Gostaria de deixar uma ideia para você(ês) do blog:
Se precisarem de alguém para revisão de conteúdo, eu me disponho. Não possuo formação acadêmica ainda, mas possou livros nos quais venho estudando e aprendendo todos os dias.
Para contato meu email:
leadlevelprogrammer@gmail.com