domingo, 12 de abril de 2009

Assembly - goto x,y

No pascal (onde aprendi a programar), existia uma biblioteca que eu não lembro o nome que dava um comando que colocava o cursor em um ponto da tela. Depois, era só escrever que ele colocava o texto ali.

Pois bem, vamos fazer isso em assembly! É um longo código:

.MODEL SMALL
.STACK 200h
.386

.DATA
Message db "Hello World$"

.CODE

;
;Posiciona o cursor em posicao dh (linha) e dl (coluna)
;
posic:
push bx
push ax
mov bh, 0 ;pagina
mov ah, 2 ;numero do servico de BIOS
int 10h ;chama a interrupcao
pop ax
pop bx
ret

escreve:
push ax ;empilhar tudo o que usamos (para nao corromper outro codigo)
push dx
push ds

mov ax, seg Message ;faz a escrita
mov dx, offset Message
mov ds, ax
mov ah, 09h
int 21h

pop ds ;volta tudo o que empilhamos
pop dx
pop ax
ret

Start:
xor dh, dh ;escrever na coordenada 0,0
xor dl, dl
call posic
call escreve

mov dh, 1 ;escreve na coordenada 1,1
mov dl, 1
call posic
call escreve

mov dh, 1 ;escreve a mensagem no fim da primeira linha, em 1,79
mov dl, 79
call posic
call escreve

mov ax, 4c00h ;retorna para o SO (DOS)
int 21h
End Start


Aqui já temos várias coisas novas. O programa é dividido em partes (como funções), que são executadas através de "call".

O que temos de novo aqui é o uso da pilha, identificada através da diretiva:
.STACK 200h

Ela é usada através do push e do pop. Como todas as operações são feitas com os registradores e só temos 4, então precisamos de espaço para guardar os valores. "push" coloca na pilha, "pop" retira dela, sempre usando o registrador passado por parâmetro. Nenhuma validação é feita, então dá pra empilhar ax e ler bx...

Em "posic", você pode ver que a idéia das interrupções é sempre a mesma: empilhar os registradores, setar os que a interrupção vai usar, chamar a interrupção e desempilhar tudo. No fim, o "ret" manda o fluxo de execução (ou seja, o IP - Instruction Pointer) de volta para quem o chamou...

Uma lista de interrupções pode ser encontrada em http://www.emu8086.com/assembly_language_tutorial_assembler_reference/8086_bios_and_dos_interrupts.html
A lista de comandos assembly para os processadores da Intel estão em http://www.intel.com/software/products/compilers/embedded/toolsuite/docs/compiler/assembler/asxscale_p.htm

Nenhum comentário: