Of the multitude of items that need to be checked when linking assembler to pascal, the following are most important:
Although some languages (eg. C) allow the programmer to write modules in high-level language and link these to a main program in assembler, this is not possible with Turbo Pascal. It is only possible to write procedures in assembler and link these to pascal, which must contain the main program body.
In order to keep the following examples simple, all parameters and return values are assumed to be of type either byte or word. Turbo Pascal has some advanced features for linking to assembler modules but lots of these are very specific to Turbo Pascal. For further information, consult the Turbo Pascal Reference Manual.
program ExternalDeclarations;
procedure readsint; external; { define readsint as being in another module }
procedure writesint; external;{ define writesint as being in another module }
{$L ioasm.obj} { include ioasm module object code }
begin
readsint; { read in a value into AX }
writesint; { output the value in AX }
end.
DOSSEG
.MODEL SMALL
.DATA
.CODE
PUBLIC samplefunc ; declare that samplefunc is to be used in other
; modules
samplefunc PROC ; stores a specific integer value into AX
mov ax,1234
ret
samplefunc ENDP
END
program ExternalDeclarations;
function samplefunc : word; external;
{ define samplefunc as being in another module }
{$L sample18.obj} { include sample18 module object code }
begin
writeln ('The value is : ', samplefunc);
{ output return value from ASM module }
end.
Just as a block of pascal code is defined by a begin and end, a block of inline assembler code is defined by an asm and end. Strict assembly language procedures are declared to be assembler at the end of the procedure/function declaration. There are of course certain points that must be noted:
program InlineDemo;
var
Equip : word;
begin
asm { assembler statements }
int 11h { get equipment list }
mov Equip,ax { save in variable Equip }
end;
Writeln ('The equipment word for this computer is : ', Equip);
end.
program MemoryDemo;
var
Equip : word;
begin
Equip:=MemW[$0040:$0010]; { get equipment list from BIOS Data Area }
Writeln ('The equipment word for this computer is : ', Equip);
end.
program InlineDemo;
const
VideoSegment = $B800; { assume C/E/VGA mode }
procedure ClrScr; assembler;
{ procedure to clear the screen }
asm
mov ax,VideoSegment { set the video segment }
mov es,ax
mov cx,25*80 { get number of characters on screen }
xor bx,bx { set start position on screen }
@@1:
mov byte ptr es:[bx],0 { clear character }
add bx,2 { move to next position }
loop @@1
end;
procedure GotoXY ( x, y : byte ); assembler;
{ procedure to move the cursor to the specified coordinates }
asm
mov dh,y { set DH=y-1 }
dec dh
mov dl,x { set DL=x-1 }
dec dl
mov bh,0 { set page number=0 }
mov ah,2 { set service number }
int 10h { call video interrupt }
end;
function GetCharacter ( x, y : word ) : byte; assembler;
{ procedure to return the character at a certain position on the screen }
asm
mov ax,y { y }
dec ax { y-1 }
mov dx,160
mul dx { 160*(y-1) }
mov bx,x { x }
dec bx { x-1 }
shl bx,1 { 2*(x-1) }
add bx,ax { BX=160*(y-1) + 2*(x-1) }
mov ax,VideoSegment { set ES to video segment }
mov es,ax
mov ax,es:[bx] { get character }
end;
begin
ClrScr; { clear screen }
GotoXY (10, 10); { move cursor }
Writeln ('X'); { output X at 10,10 }
Writeln (Chr (GetCharacter (10, 10)));
{ get/output the character at 10,10 }
end.