The built-in assembler allows you
to access almost all Object Pascal identifiers in assembler expressions,
including constants, types, variables, procedures, and functions. In addition,
the built-in assembler implements the special symbol @Result, which corresponds
to the Result variable within the body of a function. For example, the
function
function
Sum(X, Y: Integer): Integer;
begin
Result := X + Y;
end;
could be written in assembler as
function
Sum(X, Y: Integer): Integer; stdcall;
begin
asm
MOV EAX,X
ADD EAX,Y
MOV @Result,EAX
end;
end;
The following symbols cannot be
used in asm statements:
· Standard
procedures and functions (for example, WriteLn and Chr).
· String,
floating-point, and set constants (except when loading registers).
· Labels
that aren’t declared in the current block.
· The @Result
symbol outside of functions.
The following table summarizes the
kinds of symbol that can be used in asm statements.
|
Symbol |
Value |
Class |
Type |
|
Label |
Address of label |
Memory reference |
Size of type |
|
Constant |
Value of constant |
Immediate value |
0 |
|
Type |
0 |
Memory reference |
Size of type |
|
Field |
Offset of field |
Memory |
Size of type |
|
Variable |
Address of variable |
Memory reference |
Size of type |
|
Procedure |
Address of procedure |
Memory reference |
Size of type |
|
Function |
Address of function |
Memory reference |
Size of type |
|
Unit |
0 |
Immediate value |
0 |
|
@Result |
Result variable offset |
Memory reference |
Size of type |
With optimizations disabled, local
variables (variables declared in procedures and functions) are always allocated
on the stack and accessed relative to EBP, and the value of a local variable
symbol is its signed offset from EBP. The assembler automatically adds [EBP] in
references to local variables. For example, given the declaration
var
Count: Integer;
within a function or procedure, the
instruction
MOV EAX,Count
assembles into MOV EAX,[EBP-4].
The built-in assembler treats var
parameters as a 32-bit pointers, and the size of a var parameter is
always 4. The syntax for accessing a var parameter is different from
that for accessing a value parameter. To access the contents of a var
parameter, you must first load the 32-bit pointer and then access the location
it points to. For example,
function Sum(var
X, Y: Integer): Integer; stdcall;
begin
asm
MOV EAX,X
MOV EAX,[EAX]
MOV EDX,Y
ADD EAX,[EDX]
MOV @Result,EAX
end;
end;
Identifiers can be qualified
within asm statements. For example, given the declarations
type
TPoint = record
X, Y: Integer;
end;
TRect = record
A, B: TPoint;
end;
var
P: TPoint;
R: TRect;
the following constructions can be used in
an asm statement to access fields.
MOV EAX,P.X
MOV EDX,P.Y
MOV ECX,R.A.X
MOV EBX,R.B.Y
A type identifier can be used to
construct variables on the fly. Each of the following instructions generates
the same machine code, which loads the contents of [EDX] into EAX.
MOV EAX,(TRect PTR [EDX]).B.X
MOV EAX,TRect([EDX]).B.X
MOV EAX,TRect[EDX].B.X
MOV EAX,[EDX].TRect.B.X
内建汇编程序允许在汇编表达式中访问几乎所有的Object Pascal标识符,包括常量、类型、变量、过程、函数等。除此之外,内建汇编程序实现了特殊符号
@Result ,它对应于在函数主体中的Result变量。例如,函数
function
Sum(X, Y: Integer): Integer;
begin
Result := X + Y;
end;
可以用汇编语言写成
function
Sum(X, Y: Integer): Integer; stdcall;
begin
asm
MOV EAX,X
ADD EAX,Y
MOV @Result,EAX
end;
end;
下列符号不能用在asm语句中:
· 标准过程和函数(如WriteLn和Chr等)。
· 串、浮点以及常量(寄存器加载时除外)。
· 不能在当前块中声明的标号。
· 在函数之外的@Result符号。
下表摘要列出了可以用在asm语句中的符号种类:
|
符号 |
值 |
分类 |
类型 |
|
标号 |
标号的地址 |
内存引用 |
类型尺寸 |
|
常量 |
常量的值 |
立即值 |
0 |
|
类型 |
0 |
内存引用 |
类型尺寸 |
|
域 |
域的偏移量 |
内存 |
类型尺寸 |
|
变量 |
变量的地址 |
内存引用 |
类型尺寸 |
|
过程 |
过程的地址 |
内存引用 |
类型尺寸 |
|
函数 |
函数的地址 |
内存引用 |
类型尺寸 |
|
单元 |
0 |
立即值 |
0 |
|
@Result |
Result变量的偏移量 |
内存引用 |
类型尺寸 |
对于不优化的情况,局部变量(声明在过程和函数中的变量)总是在栈中分配且其访问与EBP相关。局部变量符号的值位于其在EBP中标记的偏移量。汇编程序自动增加在局部变量的引用中增加
[EBP] 。例如,给出如下声明:
var
Count: Integer;
在函数或过程中,下面的指令
MOV EAX,Count
汇编为MOV EAX,[EBP-4]。
内建汇编程序把var参数视为32位的指针,以及var参数的尺寸总是4。访问var参数的语法与访问变量参数的语法不同。要访问var参数的内容,则必须首先加载32位指针,然后访问其指向的位置。例如,
function Sum(var
X, Y: Integer): Integer; stdcall;
begin
asm
MOV EAX,X
MOV EAX,[EAX]
MOV EDX,Y
ADD EAX,[EDX]
MOV @Result,EAX
end;
end;
在asm语句中可以对标识符进行限定。例如,给出如下声明
type
TPoint = record
X, Y: Integer;
end;
TRect = record
A, B: TPoint;
end;
var
P: TPoint;
R: TRect;
下面的指令序列可以用在asm语句中访问域:
MOV EAX,P.X
MOV EDX,P.Y
MOV ECX,R.A.X
MOV EBX,R.B.Y
类型标识符可以用于快速创建变量。下列每个指令都产生相同的机器代码,它们加载
[EDX] 的内容到EAX中。
MOV EAX,(TRect PTR [EDX]).B.X
MOV EAX,TRect([EDX]).B.X
MOV EAX,TRect[EDX].B.X
MOV EAX,[EDX].TRect.B.X