X86 匯編/FASM 語法
FASM採用Intel語法, 符號名分大小寫.
一個FASM源碼文件由命令行, 標籤行, 指示符行, 注釋行組成. 注釋可單獨一行, 也可尾於其他行. 行尾符不分Windows或Linux. 行尾反斜槓'\'用於續行.
源碼由詞構成. 詞用於各種命名. 組成詞的字符分三種:
- 單符: +-*/= <>() []{} :, |&~# ` 每個單獨成詞, 不與其它字符結合成詞
- 引符: 單引號和雙引號. 成對使用內含單符或名符構成字串. 連續多個單引號或雙引號視為一個
- 名符: 單符和引符之外所有符號, 用於構詞. 詞首尾以空格或單符為界與他者分開.
命令語法
[編輯]每個命令行含:
助记符 零个或多个操作数(Operand) ; 注释, 这是命令行的一般形式
這些操作數隔以逗號加零個或多個空格. 操作數可以是暫存器, 立即數或內存數, 前置以尺寸符來限定大小, 但暫存器名字蘊尺寸, 不可前置以尺寸符. 立即數可為任何算式. [內存地址, 可為任何算式] 表示取該地址內的數. 也可用 ptr 內存地址 的方式. 例
mov word [0x55aa55aa], 0x12345678
等价于
mov word ptr 0x55aa55aa, 0x12345678
尺寸符 | 位數 | 字節數 |
---|---|---|
byte | 8 | 1 |
word | 16 | 2 |
dword | 32 | 4 |
fword | 48 | 6 |
pword | 48 | 6 |
qword | 64 | 8 |
tbyte | 80 | 10 |
tword | 80 | 10 |
dqword | 128 | 16 |
xword | 128 | 16 |
qqword | 256 | 32 |
yword | 256 | 32 |
類 | 位數 | 名 | |||||||
---|---|---|---|---|---|---|---|---|---|
通用 | 8 | al | cl | dl | bl | ah | ch | dh | bh |
16 | ax | cx | dx | bx | sp | bp | si | di | |
32 | eax | ecx | edx | ebx | esp | ebp | esi | edi | |
段 | 16 | es | cs | ss | ds | fs | gs | ||
控制 | 32 | cr0 | cr2 | cr3 | cr4 | ||||
除障 | 32 | dr0 | dr1 | dr2 | dr3 | dr6 | dr7 | ||
FPU | 80 | st0 | st1 | st2 | st3 | st4 | st5 | st6 | st7 |
MMX | 64 | mm0 | mm1 | mm2 | mm3 | mm4 | mm5 | mm6 | mm7 |
SSE | 128 | xmm0 | xmm1 | xmm2 | xmm3 | xmm4 | xmm5 | xmm6 | xmm7 |
AVX | 256 | ymm0 | ymm1 | ymm2 | ymm3 | ymm4 | ymm5 | ymm6 | ymm7 |
AVX-512 | 512 | zmm0 | zmm1 | zmm2 | zmm3 | zmm4 | zmm5 | zmm6 | zmm7 |
Opmask | 64 | k0 | k1 | k2 | k3 | k4 | k5 | k6 | k7 |
界 | 128 | bnd0 | bnd1 | bnd2 | bnd3 |
內存格
[編輯]CPU處理數據時, 暫存器容量有限, 大部分數據都是存在記憶體中. 那怎樣存取記憶體中的數據呢? 可以想像記憶體中有各種尺寸的格子, 就叫內存格好了. 格之最小單元為一字節. 計算機非常靈活, 可以定義和預留任何尺寸的格. 常見格尺寸與暫存器尺寸一樣, 方便數據交換. 大格常用於跟硬盤交換數據, 主要是文件.
1. 內存格的定義:
- 定義單個或多個數據:
数据定义指示符 一个或多个算式 ;算式值即格之内容
例
db 0x55, 0xaa, 0x55 ;定义三个字节格值分别为0x55, 0xaa, 0x55
- 定義字串:
数据定义指示符 任意长字串 ;字串即格之内容, 数据定义指示符db定义字节串; du定义词串, 每个词高字节为0
- 定義長指針:
数据定义指示符 算式1:算式2 ;此处数据定义指示符为dp, df, dd, dt之一, 用于定义指针.
例
dp或df 式1:式2 ;定义之长指针高字=式1, 低双字=式2
dd 式1:式2 ;定义之长指针高字=式1, 低字=式2
dt 式1:式2 ;定义之长指针高字=式1, 低四字=式2
當dt只帶一個算式時, 此算式值用於FPU擴展雙精度浮點值.
- 定義多個備份:
数据定义指示符 备份数 dup 一个或(多个算式, 算式间隔以逗号) ;定义多个备份, 定义<备份数>个<一个或(多个算式, 算式间隔以逗号)>备份.
- 從文檔中取內容:
file '档名'{:档内偏移, 默认档首},{要取字节数, 默认取至档尾} ;算式值即格之内容, 花括号参数可选
例
file '雪山飞狐' ;取文档'雪山飞狐'全部内容
file '雪山飞狐':100h, 1024 ;从'雪山飞狐'偏移100h处往后取1024字节
2. 內存格預留:
数据预留指示符 格尺寸; 格尺寸可为任何算式
數據定義指示符和數據預留指示符統稱數據指示符. FASM中的數據指示符見下表.
尺寸/字節 | 定義符 | 預留符 |
---|---|---|
1 | db,file | rb |
2 | dw,du | rw |
4 | dd | rd |
6 | dp,df | rp,rf |
8 | dq | rq |
10 | dt | rt |
值, 恆量, 標籤, 特殊符號與算式
[編輯]算式
[編輯]算式可以是單獨的值, 恆量, 標籤, 也可以是值, 恆量, 標籤, 算符(算術符和位算符)和括號構成的算數表達式. 算式值在源碼編譯時確定, 靶容器溢出或超出FASM能力會有編譯錯誤提示. 算符有不同的優先級, 可被括號改變. 在下面的算符優先級表中, 數值大優先級高.
算符 | 優先級 |
---|---|
+ - | 0 |
* / | 1 |
mod | 2 |
and or xor | 3 |
shl shr | 4 |
not | 5 |
bsf bsr | 6 |
rva plt | 7 |
表中算符含義:
- +,-,*,/為標準算術符, mod為取余
- and, or, xor, shl, shr, bsf, bsr 和 not為位算符, 操作同同名匯編指令
- rva和plt為特殊單目算符, 用於各類地址轉換, 限用於極少匯編輸出程序中, 具體操作與上下文相關.
值
[編輯]- 整數默認為十進制表示. 二進制後綴以b, 八進制後綴以o, 十六進制後綴以h或前綴以0x(C語言風格)或$(Pascal風格, 不建議使用)
- 算式中的字串被轉換成整數, 權序從左至右升高, 與日常書寫順序相反.
- FASM不支持編譯時進行浮點數運算, 算式中只能含單獨的單精度浮點數, 後綴以f, 或含小數點, 或書以科學計數法. 如2f, 2.0, 2E0表示同一浮點數, 而2是整數.
特殊符號
[編輯]4個可用於算式中的特殊符號:
- $ 當前偏移
- $$ 當前供數空間基址
- % 循環源碼當前循環次數
- %t 編譯時之時戳
恆量與標籤
[編輯]過多數值會造成程序難讀. 對數值取名, 即得恆量與標籤.
- 定義恆量
恒量名=算式 ;可定义多次, 用式取其前面行中该恒量名最近一次定义. 若只定义一次, 可在其定义的源码文件中任何位置引用, 不分前后
例:
身高=165 ;
- 定義標籤. 標籤只可定義一次, 可在其定義的源碼文件中任何位置引用, 不分前後. 標籤實為指針.
1. 碼段中的標籤用於標記碼位:
标签名: {指令行} ;标签名后缀以冒号即定义了该标签, 其值为所在码中此处地址, 用于标记码位. 花括号命令行可选.
例:
开始: ;
2. 數段中的標籤用於標記數值首地址:
标签名 数据指示符 一个算式或(多个算式隔以逗号) ;标签名即该处算式编译后数值内存首址, 为指针名, 类型由数据指示符确定. 见例.
例
身高 db 165, 170, 181 ; 定义了标签身高, 身高存储的是165的地址, 乃字节指针
mov ax,身高 ; 地址搬入ax
mov al,[身高] ; 165搬入al
mov al,ptr 身高 ; 165搬入al
mov ax,[身高] ; 编译错, 源靶尺寸不匹配
mov ax,word [身高] ; 165, 170搬入ax, al=165, ah=170
3. 用 label 指示符定義標籤
label 标签名 {:} {尺寸符} {at} {算式, 其值乃标签之内容} ; 最灵活的标签定义方式, 若无参数算式, 则标签值为当前地址
例
label 双高 word at 身高 ; '身高'为上例之标签, '双高'定义为始于'身高'地址的16位值(两个字节)的标签
mov ax, [双高] ; 等价于 mov ax,word [身高]
4. 特殊標籤:
- 局部標籤(層次標籤)
- 前綴以'.'(點)之標籤名為局部標籤, 前綴以其前面最近的全局標籤構成此標籤全名, 其簡名可在下一個全局標籤前隨處使用
- 前綴以'..'(雙點)之標籤名為全局標籤的引用, 不能用於局部標籤的新前綴
- 無名標籤
- @@ 無名標籤, 數目不限
- @b,@r 引用前面最近的無名表情 (b-before, 前面)
- @f 引用後面最近的無名標籤 (f-follow, 隨後)
跳轉與呼叫
[編輯]跳转或呼叫 尺寸符 远近符 [地址算式] ; 远近符: short, near, far
例:
jmp dword [0] ; 16位模式中默认为远跳, 32位模式中默认为近跳, 可用远近符修改
jmp near dword [0] ; 强制为近跳
jmp far dword [0] 强制为远跳
跳转或呼叫 尺寸符 立即数 ; 默认生成最短跳, 除非用远近符修改
尺寸設定
[編輯]默認生成指令之規則為最小資源化, 除非有尺寸符明確指定.
指令 {尺寸符} [地址] ; 无尺寸符时默认以最短位移生成最小指令
指令 操作数, {尺寸符} 立即数 ; 这里指令为adc, add, and, cmp, or, sbb, sub 和 xor, 无尺寸符时, 若立即数可表为8位有符号数, 则16-位或32-位操作数默认生成为8位. imul指令尾操作数为立即数时遵循同样规则
push {尺寸符} 立即数 ; 无尺寸符时, 此立即数于16位模式中当作词, 32位模式中作双词, 若可行则生成8位式指令. 尺寸符word或dword强制生成push长式指令
pushw或pushd强制fasm生成16位或32位码而非长式指令.