The asm statement
function Add(A, B: Integer): Integer;
asm
mov eax, A // Delphi: parameters are by name
add eax, B
end; // the result is left in EAX
procedure Pause;
begin
asm
nop
nop
end;
end;
asm … end is a statement that holds assembly language
instructions, one to a line or separated by semicolons. It may stand among Pascal
statements, or be the whole body of a routine (as above, with no
begin; the routine may also carry the assembler directive).
Turbo Pascal 6 introduced it (Turbo Pascal 5.x and earlier had only inline),
and Delphi and Free Pascal keep it for the processors they target. The assembler
understands Pascal names: variables, parameters, constants, types and routines can be
used as operands.
Syntax inside the block
- Instructions are the processor’s mnemonics and operands:
mov eax, [ebx+4],rep movsb,fld qword ptr [Value]. Mnemonics and register names do not depend on case. - Comments are the Pascal ones:
{ … },(* … *)and//. A semicolon is not a comment but a separator between instructions (Delphi). A wordendinside a comment or string does not end the block. - Labels start with
@@:@@loop:is a label local to the asm block. A label may also be a Pascallabeldeclared in the routine. - Numbers are Pascal’s (
$FF,255) and the assembler’s: a hexadecimal number ending inh(0FFh, starting with a digit) and, in Free Pascal,0xFF. - Strings are Pascal’s, in single quotes.
db 'text', 0defines data bytes.db,dw,dd,dqdefine data in the code. - Operators in operands include
+ - * /,[ ],ptr,offset,type,high,low,@Resultand the field selector.. - The end of the block is the word
end. The block holds nobegin.
Registers and the result
- In Delphi’s 32-bit
registercalling convention the first three parameters arrive inEAX,EDXandECX(for a method,Selftakes the first), and an integer or pointer result goes back inEAX, a real inST(0), and a 64-bit integer inEDX:EAX. An assembler routine must keepEBX,ESI,EDIandEBPand may change the others. - On 64-bit Windows the native convention passes the first four parameters in
RCX,RDX,R8,R9, and results inRAX(orXMM0). Delphi’s 64-bit assembler accepts the directives.noframe,.pushnv,.savenvand.paramsto control the frame. - In Turbo Pascal for DOS,
AX,BX,CX,DX,SI,DI,ES,DShold values;DS,SS,BPandSPmust be preserved. Function results go inAL,AX, orDX:AX. Result(or the function name) may be used as an operand to store a result that is not in a register:mov Result, eax.
Free Pascal
{$asmmode intel}
function Swap32(X: LongWord): LongWord; assembler; nostackframe;
asm
bswap eax
end;
{$asmmode att} { x86-64 Linux: the first two arguments are in RDI and RSI }
procedure Copy16(Src, Dst: Pointer); assembler;
asm
movups (%rdi), %xmm0
movups %xmm0, (%rsi)
end;
- The syntax is chosen with
{$ASMMODE intel},attordirect. Intel syntax is the one Delphi code uses. In AT&T syntax registers start with%, immediate values with$, the source comes first (movl %eax, %ebx) and the operand size is part of the mnemonic suffix. Indirectmode the text goes straight to the assembler. - Free Pascal has an assembler reader for each target processor it supports (Intel x86 and x86-64 among them), and the instructions inside
asmare those of that processor. - The old form
asm instructions end ['eax', 'ebx'];with a list of registers the block changes is also accepted. - An
assemblerroutine withnostackframeomits the prologue.
Inline machine code (Turbo Pascal)
procedure Cli; inline($FA); { a routine that is one machine instruction }
function Swap(X: Word): Word;
inline($58/$86/$C4); { pop ax / xchg ah, al }
begin
inline($CD/$20); { a statement: int 20h }
end.
inline takes machine code bytes separated by /, as constants or
names with < and > for the low and high byte. It is a statement, or the
whole body of a routine, which then is put at each call. Free Pascal and Delphi
accept inline as a directive that asks for the body to be expanded, which is a
different thing. Turbo Pascal 5 and earlier use this form for assembly.
How the viewer reads it
The file viewer finds the end that closes an asm block, ignoring the
word inside comments and strings, and colours what is between with its assembly
scanner: the mnemonic at the start of the instruction as a keyword, registers as
variables, @@label: labels as tags, $FF and 0FFh as numbers, and Pascal
comments and strings as such. A word that continues an
asm block in a member access (X.asm) is not an asm block.