A primeira subrotina
Começando a criação de código reaproveitável

Uma das grandes vantagens de estarmos programando em asm, de dentro do Delphi, é que podemos aproveitar todas as estruturas de programação dele e ainda brincar com as instruções mais poderosas da face da Terra, digo, da programação de computadores. Porém isso tem um custo: trabalho. Muito trabalho.

Vamos então criar uma rotina (procedure) que apenas e tão somente crie um retângulo na tela, com uma determinada cor (claro, vamos aproveitar o conhecimento da página anterior).

Para passar parâmetros de um lugar para outro, poderíamos usar normalmente a estrutura do pascal, mas aconselho a deixá-la de lado e lançar mão de variáveis globais para esse propósito. É mais seguro assim.

var
Px,Py,Lrg,Alt,Cor: dword;

Temos então Px e Py que indicarão as coordenadas iniciais ou posição na tela a ser usada; Lrg e Alt como largura e altura da figura a ser desenhada e Cor contendo o valor 32 bits da cor usada para plotar. A forma de uso desta estrutura é simples: carregamos cada uma das variáveis com um determinado valor e chamamos a subrotina (procedure). Por exemplo:

procedure TForm1.FormClick(Sender: TObject);
begin
Px:= 10; Py:= 10; Lrg:= 100; Alt:= 20;
Cor:= $00FF0000;
Box;
Canvas.Draw(0,0,Tela);
end;

Box portanto é nossa rotina de desenhar retângulos na tela.

procedure TForm1.Box;
asm
push ebx //preserva ebx
//Calcular o endereço da coordenada Px,Py
mov ebx,Init //início da tela 0,0
mov eax,Difr
mov ecx,Py
mul ecx //Py * Difr
sub ebx,eax //calcula linha Py
mov eax,4
mov ecx,Px
mul ecx //Px * 4
add ebx,eax //endereço da coord Px,Py
//Plotar linha horizontal a partir de Px,Py
mov ecx,Lrg
mov eax,Cor
@Lp1:
mov [ebx],eax
add ebx,4
loop @Lp1
//Plotar linha vertical a partir de Px+Lar,Py
sub ebx,4 //recua um ponto
mov ecx,Alt
@Lp2:
mov [ebx],eax
sub ebx,Difr
loop @Lp2
//Plotar linha horizontal a partir de Px+Lar,Py+Alt
add ebx,Difr //recua um ponto
mov ecx,Lrg
@Lp3:
mov [ebx],eax
sub ebx,4
loop @Lp3
//Plotar linha vertical a partir de Px,Py+Alt
add ebx,4 //recua um ponto
mov ecx,Alt
@Lp4:
mov [ebx],eax
add ebx,Difr
loop @Lp4
pop ebx
end;

Estude com atenção a listagem e veja como o retângulo é desenhado em seqüência, linha a linha, como se o "lápis" não saísse do papel em nenhum momento. Trabalhoso, não é mesmo? Em pascal do Delphi isso seria mais ou menos o mesmo que fazer o seguinte:

  Canvas.Rectangle(10,10,110,30);

Prosseguindo...

Uma das observações que podemos fazer aqui é que usaremos inúmeras vezes o cálculo da posição inicial na tela, para a plotagem ou impressão de qualquer figura, desenho, letra, ponto, etc. Então, nada mais natural que transformemos esse cálculo em uma rotina separada e obviamente precisaremos de mais uma variável global para conter o resultado (o endereço em questão).

var
Ender: dword;
procedure TForm1.PosXY;
asm
push ebx //preserva ebx
//Calcular o endereço da coordenada Px,Py
mov ebx,Init //início da tela 0,0
mov eax,Difr
mov ecx,Py
mul ecx //Py * Difr
sub ebx,eax //calcula linha Py
mov eax,4
mov ecx,Px
mul ecx //Px * 4
add ebx,eax //endereço da coord Px,Py
mov Ender,ebx
pop ebx
end;

A rotina para desenhar o retângulo fica então com a seguinte modificação:

procedure TForm1.Box;
asm
push ebx //preserva ebx
call PosXY
mov ebx,Ender
//Plotar linha horizontal a partir de Px,Py
...

O interessante desse procedimento é que mantemos à mão o endereço inicial para plotagem da figura e isso pode ser útil de diversas formas. Pense em algumas delas, enquanto a página seguinte é baixada para o seu navegador.


Download...
Clique no link para fazer o download dos arquivos fonte tratados nessa página.

asm2.zip... (160 Kb) Fontes do project 2.
 
online