允许使用特殊指令结构的汇编代码。
语法
Asm
architecture-dependent instructions
End Asm
Or
Asm architecture-dependent instructions
说明
Asm块用于在程序中插入特定的机器码指令,以执行不能使用该语言的功能执行的操作,或手动优化性能敏感的代码段。
目前的FreeBASIC编译器目前只生成基于Intel
80x86机器的代码;然而,将来,编译器可能被移植到不支持相同指令集的平台上。因此,只有在必要时才使用
Asm块,并且如果可能,应该提供仅限FreeBASIC的替代方案。
可以使用括号内的
Function关键字设置函数的返回值,如下面的示例所示。
Asm块注释与惯例FreeBASIC
注释具有相同的语法 - 使用FreeBASIC类似的“
'”注释,而不像“
;”一样,在汇编代码中。
x86具体:
句法
内联汇编器的语法是英特尔语法的简化形式。大多数x86汇编程序使用英特尔语法,如MASM,TASM,NASM,YASM和FASM。一般来说,指令的目的地是首先放置,其次是源。由程序定义的变量和函数可以在
Asm块中引用。FreeBASIC使用的汇编程序是GAS,使用
.intel_syntax noprefix指令,
Asm块通过未修改的方式传递,除了替换局部变量名称以进行堆栈帧引用,并注释删除。
指令语法大体上与FASM使用相同,一个重要的区别是GAS需要大小设置后跟“
ptr”。
' Assuming "blah" is a FB global or local UINTEGER variable
mov eax, [blah] ' OK: size is apparent from eax
inc [blah] ' Not OK: size is not given
inc dword [blah] ' Not OK: size given, but still not accepted by GAS
inc dword Ptr [blah] ' OK: "ptr" is needed by GAS here
注册保存
当Asm块打开时,寄存器ebx,esi和edi被推送到堆栈,当块关闭时,这些寄存器从堆栈中弹回。这是因为大多数或所有OS使用x86 CPU需要保留这些寄存器。因此,您可以自行使用这些寄存器,而无需明确保留它们。您不应该更改esp和ebp,因为它们通常用于解决局部变量。
注册名称
x86架构的寄存器的名称如下写在Asm块中:
- 4字节整数寄存器:eax,ebx,ecx,edx,ebp,esp,edi,esi
- 2字节整数寄存器:ax,bx,cx,dx,bp,sp,di,si(低字节的4字节e - 寄存器)
- 1字节整数寄存器:al,ah,bl,bh,cl,ch,dl,dh(低字节和高字节的2字节 - x寄存器)
- 浮点寄存器:st(0),st(1),st(2),st(3),st(4),st(5),st(6),st(7)
- MMX寄存器(别名到浮点寄存器):mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7
- SSE寄存器:xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7
指令系统
请参阅这些外部参考:
不安全的说明
请注意,FreeBASIC编译器为x86生成32位保护模式代码,通常在非特权用户级别运行;因此,特权和敏感指令将组合良好,但可能无法正常工作或导致运行时“一般保护故障”,“非法指令”或SIGILL错误。以下是Intel Pentium 4和Xeon的特权和敏感指示:
- cli *1
- clts
- hlt
- in *1
- ins *1
- int *1
- into *1
- invd
- invlpg
- lgdt
- lidt
- lldt
- lmsw
- ltr
- movto / from CRn,DRn,TRn
- out *1
- outs *1
- rdmsr
- rdpmc *2
- rdtsc *2
- sti *1
- str
- wbinvd
- wrmsr
- 所有SSE2及更高版本的说明* 2
* 1:对IOPL敏感,在DOS中很好
* 2:对CR4中的许可位敏感,见下文
当在Ring 0 DPMI内核上运行时,特权指令将在DOS中正常工作,例如(非默认)Ring 0版本的CWSDPMI,WDOSX或D3X,但大部分当从DPMI代码执行时,它们并不真正有用和危险。RDTSC(读时间戳计数器)已经被大多数或所有操作系统所允许。
然而,随着多核和休眠CPU的出现,RDTSC的有用性已经减弱。在CPU初始化之后,SSE2和更高版本的指令被禁用,Windows和Linux通常会启用它们,在DOS中它是DPMI主机的业务:HDPMI32将启用它们,CWSDPMI将不会。INT指令仅在DOS版本/目标下可用,请注意,它与实模式DOS的工作方式略有不同,另见FaqDOS。
不能从
Asm块更改分段寄存器(
cs,
ds,
es,
fs,
gs),但在某些情况下,DOS端口除外(请注意,它们不工作与实模式DOS相同,另见FaqDOS)。操作系统或DPMI主机负责内存管理;保护模式中段(选择器)的含义与实模式存储器寻址非常不同。
请注意,即使运行权限不足,操作系统或DPMI主机也可以在功能上决定“模拟”这些“不安全”指令,从而引发“可见”崩溃(从HDPMI32的一些CRx工作中读取),或“虚拟”(没有发生任何事情,教学将默认通过,像NOP)。
例子
''这是x86架构的一个例子。
Function AddFive(ByVal num As Integer) As Integer
Asm
mov eax, [num]
add eax, 5
mov [Function], eax
End Asm
End Function
Dim i As Integer = 4
Print "4 + 5 ="; AddFive(i)
4 + 5 = 9
FreeBASIC的汇编器是GCC的汇编程序AS / GAS,因此是外部程序。有些怪癖适用:
- FBC为ASM块返回的错误行与FB源文件无关。由于FBC只显示AS返回的错误,这些行与程序集文件相关。要使FreeBASIC保留它们,必须使用-R 选项(“不要删除ASM文件”)来调用编译器。
- 标签名称在ASM块内区分大小写。
方言差异
与QB差别
参考