Programando no MS-DOS

Conhecendo o ambiente do MS-DOS.

O clássico MS-DOS, antigo sistema operacional de 16 bits da Microsoft, foi muito utilizado e até hoje existem projetos relacionados a esse sistema. Existe por exemplo o FreeDOS que é um sistema operacional de código aberto e que é compatível com o MS-DOS.

A famosa "telinha preta" do Windows, o prompt de comando, muitas vezes é erroneamente chamado de MS-DOS devido aos dois usarem o mesmo shellscript chamado de Batch. Isso fazia com que comandos rodados no MS-DOS fossem quase totalmente compatíveis na linha de comando do Windows.

Mas o prompt de comandos do Windows não é o MS-DOS. Esse é apenas o Terminal do sistema operacional Windows e que usa uma versão mais avançada do mesmo shellscript que rodava no MS-DOS.

Real mode

O MS-DOS era um sistema operacional que rodava em modo de processamento real mode, o famoso modo de 16-bit que é compatível com o 8086 original.

Text mode

Existem modos diferentes de se usar a saída de vídeo, isto é, o monitor do computador. Dentre os vários modos que o monitor suporta, existe a divisão entre modo de texto (text mode) e modo de vídeo (video mode).

O modo de v√≠deo √© este modo que o seu sistema operacional est√° rodando agora. Nele o software define informa√ß√Ķes de cor para cada pixel da tela, formando assim imagens desde mais simples (formas opacas) at√© as mais complexas (imagens renderizadas tridimensionalmente). Todas essas imagens que voc√™ v√™ s√£o geradas pixel a pixel para serem apresentadas pelo monitor.

J√° o MS-DOS rodava em modo de texto, cujo este modo √© bem mais simples. Ao inv√©s de voc√™ definir cada pixel que o monitor apresenta, voc√™ define unicamente informa√ß√Ķes de caracteres. Imagine por exemplo que seu monitor seja dividido em grade formando 80x25 quadrados na tela. Ou seja, 80 colunas e 25 linhas. Ao inv√©s de definir cada pixel voc√™ apenas definia qual caractere seria apresentado naquele quadrado e um atributo para esse caractere.

Execut√°veis .COM

O formato de executável mais básico que o MS-DOS suportava era os de extensão .com que era um raw binary. Esse termo é usado para se referir a um "binário puro", isto é, um arquivo binário que não tem qualquer tipo de formatação especial.

Uma compara√ß√£o com arquivos de texto seria voc√™ comparar um c√≥digo fonte em C com um arquivo de texto "normal". O c√≥digo fonte em C tamb√©m √© um arquivo de texto, por√©m ele tem formata√ß√Ķes especiais que seguem a sintaxe da linguagem de programa√ß√£o. Enquanto o arquivo de texto "normal" √© apenas texto, sem seguir qualquer regra de formata√ß√£o.

No caso do raw binary é a mesma coisa, informação binária sem qualquer regra de formatação especial. Este executável do MS-DOS tinha como "entry point" logo o primeiro byte do arquivo. Como eu já disse, não tinha qualquer regra especial nele então você poderia organizá-lo da maneira que quisesse manualmente.

Execução do .COM

O processo que o MS-DOS fazia para executar esse tipo de executável era tão simples quanto possível. Seguindo o fluxo:

  • Recebe um comando na linha de comando.

  • Coloca o tamanho em bytes dos argumentos passados pela linha de comando no offset 0x80 do segmento do execut√°vel.

  • Coloca os argumentos da linha de comando no offset 0x81 como texto puro, sem qualquer formata√ß√£o.

  • Carrega todo o .COM no offset 0x100

  • Define os registradores DS, SS e ES para o segmento onde o execut√°vel foi carregado.

  • Faz um call no endere√ßo onde o execut√°vel foi carregado.

Perceba que a chamada do executável nada mais é que um call, por isso esses executáveis finalizavam simplesmente executando um ret. Mais simples impossível, né?

ORG | Origin

org endereço_inicial

A essa altura você já deve ter reparado que o NASM calcula o endereço dos rótulos sozinho sem precisar da nossa ajuda, né? Então, mas ele faz isso considerando que o primeiro byte do nosso arquivo binário esteja especificamente no offset 0. Ou seja, ele começa a contar do zero em diante. No caso de um executável .COM ele é carregado no offset 0x100 e não em 0, então o cálculo vai dar errado.

Mas o NASM contém a diretiva org que serve para dizer para o NASM a partir de qual endereço ele deve calcular o endereço dos rótulos, ou seja, o endereço de origem do nosso binário. Veja o exemplo:

bits 16
org 0x100

msg: db "abc"

codigo:
  mov ax, 77
  ret

O rótulo codigo ao invés de ter o endereço calculado como 0x0003 como normalmente teria, terá o endereço 0x0103 devido ao uso da diretiva org na segunda linha.

Hello World no MS-DOS

Um pequeno exemplo de "Hello World" (ou "Hi") para o MS-DOS:

hello.asm
bits 16
org 0x100

mov ah, 0x0E
mov al, 'H'
int 0x10

mov al, 'i'
int 0x10

ret

Experimente compilar como um raw binary com extens√£o .com e depois executar no Dosbox (ou FreeDOS ou qualquer projeto semelhante).

$ nasm hello.asm -o hello.com

A instrução INT e o que está acontecendo aí será explicado nos dois tópicos posteriores a esse.

Last updated