Bloky programu, které vykonávají činnost často se opakující, nazveme podprogramem. Jejich použitím zjednodušíme program. Za podprogramy pokládáme procedury a funkce. Pascal umožňuje vkládat assembler i do obyčejných podprogramů. Můžeme také tvořit podprogramy pouze v assembleru. To vyjádříme zápisem assembler za definici procedury nebo funkce. Ty potom neobsahují klasické vymezení bloku begin...end, stačí jen assemblerovské asm..end (pokud tedy tvoříme podprogram jen v assembleru, uvedeme za definici označení assembler, blok vymezíme asm...end). S parametry pracujeme v podprogramech v souladu s tím, jak jsme je přes zásobník předávali. To znamená, že k parametrům volaným hodnotou přistupujeme jako ke klasickým proměnným, k parametrům volaným odkazem přistupujeme jako k ukazatelům (dosazujeme jejich adresu instrukcí LES, LDS).
V okamžiku vstupu do podprogramu se na vrcholu zásobníku automaticky vytvoří místa pro lokální proměnné definované v části var podprogramu. V případě, že se jedná o pascalovskou funkci (není označena slovem assembler v definici), je navíc vložena speciální proměnná @RESULT určená k předání funkční hodnoty (ta je i stejného datového typu). Před návratem z funkce je obsah proměnné @RESULT automaticky předán do registrů předepsaných pro návrat hodnoty (pokud tedy tvoříme funkci s vloženým assemblerovským blokem, předáme funkční hodnotu do proměnné @RESULT, ve funkci s označením assembler vracíme funkční hodnotu v registrech, ve kterých funkční hodnotu očekává volající (AL, AX,..), jak bylo uvedeno v části o volání podprogramů). Lokální proměnné používáme stejně jako globální (s tím rozdílem, že jejich segmentová adresa není v DS).
Registr BP je v době vykonávání podprogramu nasměrován na vrcholek zásobníku v okamžiku vstupu do něj. Proto použitím nepřímé bázové adresace s pomocí tohoto registru můžeme přistupovat k:
Vzhledem k tomu, že se o tyto přepočty adres může postarat překladač, je jednodušší používat pro přístupy k proměnným a parametrům jen jejich symboly uvedené v definici podprogramu nebo části var.
Příklad:
uses crt;
procedure pocitej (a,b:word;var c,d:word);assembler;
asm
MOV
AX,a
{do registru ax, vlož hodnotu a}
ADD
AX,b
{přičti b}
LES
DI,c
{do ES:DI vlož adresu c (to je výstup součtu)}
MOV
ES:[DI],AX {na
adresu ES:DI zapiš součet}
MOV
AX,a
{to samé pro rozdíl}
SUB
AX,b
LES
DI,d
MOV
ES:[DI],AX {a na
adresu d zapiš rozdíl}
end;
function bez1 (a:word):word;assembler;
asm
MOV
AX,a
{do AX vlož hodnotu parametru a}
DEC
AX
{kdyby to nebyla čistě assemblerovská funkce,
tak}
{přidám řádek:}
{MOV
@RESULT, AX fce hodnotu pak také vrátí v AX}
end;
var a_,b_,c_,d_:word; {hlavní program}
begin
a_:=40;b_:=5;
clrscr;
pocitej (a_,b_,c_,d_);
writeln (a_,'+(-)',b_,'=',c_,'(',d_,')');
c:=bez1 (a_);
writeln (a_,'-1=',c_);
readkey;
end.