Trochę Assemblera w Pascalu

Patkoss

Trochę assembler'a w Pascalu.
Assembler niegdyś był bardzo popularnym językiem, jako język rozkazów mnemonicznych procesora zyskał sobie uznanie jako najbardziej szybki i najbardziej związany z procesorem język programowania. Tak jest po dzień dzisiejszy. Ustępuje on co prawda potencjałowi produkcyjnemu nowoczesnych narzędzi programistycznych, lecz nadal każdy szanujący się kompilator produkujący kod natywny procesora pozwala na użycie instrukcji tego języka. Nie inaczej jest z Pascal'em. Nie jest moim celem pokazanie nie wiadomo jakich cudów, lecz zachęcenie czytelnika do własnych eksperymentów w tym wymiarze.

W języku C mamy przydatną funkcję _setcursortype(), która potrafi zmienić znak kursora. Czasami programując w trybie tekstowym (czy każdy potrzebuje trybu graficznego?), przydałoby się zmienić ten znak, w Pascalu niestety nie ma takiej funkcji, więc posłużymy się assembler'em:

asm
  mov cx, 0; {do CX wartość kursora, 0 jest to kwadrat}
  mov ah, 1; {do AH 1: ustaw kursor na wartość z CX}
  int 10h;  {i przerwanie 10h wywołujemy}
end;

Kursor zmienił się na mrugający kwadrat, zamiast mrugającego podkreślenia. Jeśli chcemy przywrócić stary kursor, wpiszmy do cx wartość 1. Teraz nic nie stoi na przeszkodzie abyśmy i w Pascalu mogli się posługiwać własną funkcją (w Pascalu zakodujemy ją jako procedurę) _setcursortype():

procedure _setcursortype (cr_type: word); assembler;
asm
  mov cx, cr_type;
  mov ah, 1;
  int 10h;
end;

Jak wymusić zakończenie programu? Oczywiście możemy się posłużyć procedurą halt lub exit, runerror lub inną. Jednak możemy to wykonać także w assemblerze:

asm
  mov ah, 4ch;
  int 21h;
end;

Instrukcje te spowodują zakończenie działania programu. Zauważ, że i tym razem wywołuję przerwanie (21h to przerwanie systemu operacyjnego, 10h to przerwanie karty graficznej) wraz z odpowiednimi wartościami w rejestrach (w tym przypadku numerem funkcji do wywołania). W ten sposób korzystamy w assemblerze z funkcji (nie własnych, te z kolei wywołujemy poleceniem call). Zapewne w Pascalu często korzystasz z pętli "repeat until keypressed", to znany sposób na wstrzymanie wykonywania programu do naciśnięcia klawisza. Jednak możemy to zrobić w assemblerze.

asm
  mov ah, 08h;
  int 21h;
end;

Efekt ten sam, ale kod mniejszy i szybszy, gdyż napisany bezpośrednio dla procesora. Kompilator nie musi tłumaczyć pętli na odpowiednie instrukcje assembler'a (co robi trochę nieudolnie). Możemy także wyświetlić napis na ekranie korzystając z assemblera:

const writing:string='Hvordan har du det?$';
{napis zakonczony znakiem $, żeby było wiadomo gdzie się kończy}
begin
  asm
    mov dx, offset writing; {do DX adres łańcucha}
    mov ah, 09h; {do AH nr. odpowiedniej funkcji}
    int 21h; {i oczywiście przerwanie}
  end;

Na ekranie powinno się pojawić duńskie pytanie grzecznościowe. Lecz cóż to? Jakieś krzaczki również się pojawiły? Dzieje się tak ponieważ w plikach *.exe (inaczej niż w *.com - tam wszystko będzie poprawnie), cały program wraz z segmentami kodu i danych nie znajduje się w jednym segmencie. Jeśli zainteresujesz się tematem dowiesz się, że adres napisu powinien się znajdować w DS:DX. Celowo nie podam w tym miejscu rozwiązania, z nadzieją, że temat wyda Ci się interesujący i postanowisz samodzielnie ten problem rozwiązać.

1 komentarz

hmm a da się zrobić coś innego niż tylko kwadrat? hmm zaraz spróbuję :D