D x86 内联汇编D,作为一种系统程序设计语言,提供了内联汇编的功能。对于同一个处理器家族来说,D 的内联汇编的实现是标准化了的,例如,Intel Pentium 上的 Win32 D 编译器的内联汇编的语法同 Intel Pentium 上的 Linux D 编译器的语法是一样的。 但是,不同的 D 实现,可以依内存模型、函数调用/返回约定,参数传递约定等的不同而自由实现内联汇编。
本文描述了内联汇编的 x86 实现。
Asm指令:
标志符 : Asm指令
align 整数表达式
even
naked
db 多个操作数
ds 多个操作数
di 多个操作数
dl 多个操作数
df 多个操作数
dd 多个操作数
de 多个操作数
操作码
操作码 多个操作数
多个操作数
操作数
操作数 , 多个操作数
AsmInstruction:
Identifier : AsmInstruction
align IntegerExpression
even
naked
db Operands
ds Operands
di Operands
dl Operands
df Operands
dd Operands
de Operands
Opcode
Opcode Operands
Operands
Operand
Operand , Operands
标号汇编指令可以向其他语句一样带有标号。它们可以作为 goto 语句的目标。例如:void *pc;
asm
{
call L1;
L1:;
popEBX;
movpc[EBP],EBX;// pc 现在指向 L1 处的代码
}
align 整数表达式汇编器使用 NOP 指令进行填充,使下一条指令对齐到 整数表达式 边界上。整数表达式 的值必须是 2 的幂。 使循环代码对齐可以使得执行速度得到可观的提升。
even汇编器使用 NOP 指令进行填充,使下一条指令对齐到偶数边界上。 naked禁止编译器生成函数的建帧和退帧指令。这就意味着责任落到了使用内联汇编的程序员的头上,因此这种用法主要用于那些全部用内联汇编编写的函数。 db, ds, di, dl, df, dd, de这些伪操作用于直接向代码中插入原始数据。db 用于字节,ds 用于 16 位字,di 用于 32 位字,dl 用于 64 位字,df 用于 32 位浮点型,dd 用于 64 位双精度型,de 用于 80 位扩展实数型。它们都可应用于多个操作数。如果有操作数为字符串文字量,汇编器就认为存在一个隐含的 length 操作数,length 表示字符串中有多少了字符。每个操作数会额外使用一个字符。例如:asm
{
db 5,6,0x83; // 插入 byte 0x05、0x06 和 0x83
ds 0x1234; // 插入 byte 0x34、0x12
di 0x1234; // 插入 byte 0x34、0x12、0x00、0x00
dl 0x1234; // 插入 byte 0x34、0x12、0x00、0x00、0x00、0x00、0x00、0x00
df 1.234; // 插入 float 1.234
dd 1.234; // 插入 double 1.234
de 1.234; // 插入 extended 1.234
db "abc"; // 插入 byte 0x61、0x62、and 0x63
ds "abc"; // 插入 byte 0x61、0x00、0x62、0x00、0x63、0x00
}
操作码本文末尾列出了支持的操作码。 支持下面的寄存器。寄存器名都是大写的。
AL, AH, AX, EAX BL, BH, BX, EBX CL, CH, CX, ECX DL, DH, DX, EDX BP, EBP SP, ESP DI, EDI SI, ESI ES, CS, SS, DS, GS, FS CR0, CR2, CR3, CR4 DR0, DR1, DR2, DR3, DR6, DR7 TR3, TR4, TR5, TR6, TR7 ST ST(0), ST(1), ST(2), ST(3), ST(4), ST(5), ST(6), ST(7) MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7 特殊情况lock, rep, repe, repne, repnz, repz 这些前缀指令不能同它们修饰的指令位于同一语句,它们必须单独写成一条指令。例如:asm
{
rep ;
movsb ;
}
pause 内联汇编不支持该操作码,使用{
rep ;
nop ;
}
代替,效果是相同的。 浮点运算 使用指令的两操作数形式:fdiv ST(1);// 错误
fmul ST; // 错误
fdiv ST,ST(1);// 正确
fmul ST,ST(0);// 正确
操作操作数:
Asm表达式
Asm表达式:
Asm逻辑或表达式
Asm逻辑或表达式 ? Asm表达式 : Asm表达式
Asm逻辑或表达式:
Asm逻辑与表达式
Asm逻辑与表达式 || Asm逻辑与表达式
Asm逻辑与表达式:
Asm或表达式
Asm或表达式 && Asm或表达式
Asm或表达式:
Asm异或表达式
Asm异或表达式 | Asm异或表达式
Asm异或表达式:
Asm与表达式
Asm与表达式 ^ Asm与表达式
Asm与表达式:
Asm相等表达式
Asm相等表达式 & Asm相等表达式
Asm相等表达式:
Asm关系表达式
Asm关系表达式 == Asm关系表达式
Asm关系表达式 != Asm关系表达式
Asm关系表达式:
Asm移位表达式
Asm移位表达式 < Asm移位表达式
Asm移位表达式 <= Asm移位表达式
Asm移位表达式 > Asm移位表达式
Asm移位表达式 >= Asm移位表达式
Asm移位表达式:
Asm和表达式
Asm和表达式 << Asm和表达式
Asm和表达式 >> Asm和表达式
Asm和表达式 >>> Asm和表达式
Asm和表达式:
Asm积表达式
Asm积表达式 + Asm积表达式
Asm积表达式 - Asm积表达式
Asm积表达式:
Asm括号表达式
Asm括号表达式 * Asm括号表达式
Asm括号表达式 / Asm括号表达式
Asm括号表达式 % Asm括号表达式
Asm括号表达式:
Asm一元表达式
Asm括号表达式 [ Asm表达式 ]
Asm一元表达式:
Asm类型前缀 Asm表达式
offset Asm表达式
seg Asm表达式
+ Asm一元表达式
- Asm一元表达式
! Asm一元表达式
~ Asm一元表达式
Asm基本表达式
Asm基本表达式
整数常量
浮点数常量
__LOCAL_SIZE
$
寄存器
点标志符
点标志符
Identifier
标志符 . 点标志符
Operand:
AsmExp
AsmExp:
AsmLogOrExp
AsmLogOrExp ? AsmExp : AsmExp
AsmLogOrExp:
AsmLogAndExp
AsmLogAndExp || AsmLogAndExp
AsmLogAndExp:
AsmOrExp
AsmOrExp && AsmOrExp
AsmOrExp:
AsmXorExp
AsmXorExp | AsmXorExp
AsmXorExp:
AsmAndExp
AsmAndExp ^ AsmAndExp
AsmAndExp:
AsmEqualExp
AsmEqualExp & AsmEqualExp
AsmEqualExp:
AsmRelExp
AsmRelExp == AsmRelExp
AsmRelExp != AsmRelExp
AsmRelExp:
AsmShiftExp
AsmShiftExp < AsmShiftExp
AsmShiftExp <= AsmShiftExp
AsmShiftExp > AsmShiftExp
AsmShiftExp >= AsmShiftExp
AsmShiftExp:
AsmAddExp
AsmAddExp << AsmAddExp
AsmAddExp >> AsmAddExp
AsmAddExp >>> AsmAddExp
AsmAddExp:
AsmMulExp
AsmMulExp + AsmMulExp
AsmMulExp - AsmMulExp
AsmMulExp:
AsmBrExp
AsmBrExp * AsmBrExp
AsmBrExp / AsmBrExp
AsmBrExp % AsmBrExp
AsmBrExp:
AsmUnaExp
AsmBrExp [ AsmExp ]
AsmUnaExp:
AsmTypePrefix AsmExp
offset AsmExp
seg AsmExp
+ AsmUnaExp
- AsmUnaExp
! AsmUnaExp
~ AsmUnaExp
AsmPrimaryExp
AsmPrimaryExp
IntegerConstant
FloatConstant
__LOCAL_SIZE
$
Register
DotIdentifier
DotIdentifier
Identifier
Identifier . DotIdentifier
操作数的语法基本遵从了 Intel CPU 文档的约定。具体来说,就是右边的操作数是源操作数,左边的操作数是目的操作数。同 Intel 存在不同之处主要是为了同 D 语言的记号识别器和简单解析的目标兼容。 操作类型Asm类型前缀:
near ptr
far ptr
byte ptr
short ptr
int ptr
word ptr
dword ptr
float ptr
double ptr
extended ptr
AsmTypePrefix:
near ptr
far ptr
byte ptr
short ptr
int ptr
word ptr
dword ptr
float ptr
double ptr
extended ptr
对于操作数大小模棱两可的情况,如同:add[EAX],3;
可以使用 Asm类型前缀 消除歧义:addbyte ptr [EAX],3;
addint ptr [EAX],7;
结构/联合/类 成员偏移量假设指向聚集的指针位于一个寄存器中,如果要访问聚集的成员,应使用成员的限定名:struct Foo { int a,b,c; }
int bar(Foo *f)
{
asm
{movEBX,f;
movEAX,Foo.b[EBX];
}
}
特殊符号$ 代表下一条指令的开始地址。所以,jmp$ ;
会跳转到 jmp 后的那条指令处。
__LOCAL_SIZE 它的值会被局部堆栈帧中的局部字节数替代。当使用 naked 并且手动制定堆栈结构时,这会很方便。支持的操作码aaa
aad
aam
aas
adc
add
addpd
addps
addsd
addss
and
andnpd
andnps
andpd
andps
arpl
bound
bsf
bsr
bswap
bt
btc
btr
bts
call
cbw
cdq
clc
cld
clflush
cli
clts
cmc
cmova
cmovae
cmovb
cmovbe
cmovc
cmove
cmovg
cmovge
cmovl
cmovle
cmovna
cmovnae
cmovnb
cmovnbe
cmovnc
cmovne
cmovng
cmovnge
cmovnl
cmovnle
cmovno
cmovnp
cmovns
cmovnz
cmovo
cmovp
cmovpe
cmovpo
cmovs
cmovz
cmp
cmppd
cmpps
cmps
cmpsb
cmpsd
cmpss
cmpsw
cmpxch8b
cmpxchg
comisd
comiss
cpuid
cvtdq2pd
cvtdq2ps
cvtpd2dq
cvtpd2pi
cvtpd2ps
cvtpi2pd
cvtpi2ps
cvtps2dq
cvtps2pd
cvtps2pi
cvtsd2si
cvtsd2ss
cvtsi2sd
cvtsi2ss
cvtss2sd
cvtss2si
cvttpd2dq
cvttpd2pi
cvttps2dq
cvttps2pi
cvttsd2si
cvttss2si
cwd
cwde
da
daa
das
db
dd
de
dec
df
di
div
divpd
divps
divsd
divss
dl
dq
ds
dt
dw
emms
enter
f2xm1
fabs
fadd
faddp
fbld
fbstp
fchs
fclex
fcmovb
fcmovbe
fcmove
fcmovnb
fcmovnbe
fcmovne
fcmovnu
fcmovu
fcom
fcomi
fcomip
fcomp
fcompp
fcos
fdecstp
fdisi
fdiv
fdivp
fdivr
fdivrp
feni
ffree
fiadd
ficom
ficomp
fidiv
fidivr
fild
fimul
fincstp
finit
fist
fistp
fisub
fisubr
fld
fld1
fldcw
fldenv
fldl2e
fldl2t
fldlg2
fldln2
fldpi
fldz
fmul
fmulp
fnclex
fndisi
fneni
fninit
fnop
fnsave
fnstcw
fnstenv
fnstsw
fpatan
fprem
fprem1
fptan
frndint
frstor
fsave
fscale
fsetpm
fsin
fsincos
fsqrt
fst
fstcw
fstenv
fstp
fstsw
fsub
fsubp
fsubr
fsubrp
ftst
fucom
fucomi
fucomip
fucomp
fucompp
fwait
fxam
fxch
fxrstor
fxsave
fxtract
fyl2x
fyl2xp1
hlt
idiv
imul
in
inc
ins
insb
insd
insw
int
into
invd
invlpg
iret
iretd
ja
jae
jb
jbe
jc
jcxz
je
jecxz
jg
jge
jl
jle
jmp
jna
jnae
jnb
jnbe
jnc
jne
jng
jnge
jnl
jnle
jno
jnp
jns
jnz
jo
jp
jpe
jpo
js
jz
lahf
lar
ldmxcsr
lds
lea
leave
les
lfence
lfs
lgdt
lgs
lidt
lldt
lmsw
lock
lods
lodsb
lodsd
lodsw
loop
loope
loopne
loopnz
loopz
lsl
lss
ltr
maskmovdqu
maskmovq
maxpd
maxps
maxsd
maxss
mfence
minpd
minps
minsd
minss
mov
movapd
movaps
movd
movdq2q
movdqa
movdqu
movhlps
movhpd
movhps
movlhps
movlpd
movlps
movmskpd
movmskps
movntdq
movnti
movntpd
movntps
movntq
movq
movq2dq
movs
movsb
movsd
movss
movsw
movsx
movupd
movups
movzx
mul
mulpd
mulps
mulsd
mulss
neg
nop
not
or
orpd
orps
out
outs
outsb
outsd
outsw
packssdw
packsswb
packuswb
paddb
paddd
paddq
paddsb
paddsw
paddusb
paddusw
paddw
pand
pandn
pavgb
pavgw
pcmpeqb
pcmpeqd
pcmpeqw
pcmpgtb
pcmpgtd
pcmpgtw
pextrw
pinsrw
pmaddwd
pmaxsw
pmaxub
pminsw
pminub
pmovmskb
pmulhuw
pmulhw
pmullw
pmuludq
pop
popa
popad
popf
popfd
por
prefetchnta
prefetcht0
prefetcht1
prefetcht2
psadbw
pshufd
pshufhw
pshuflw
pshufw
pslld
pslldq
psllq
psllw
psrad
psraw
psrld
psrldq
psrlq
psrlw
psubb
psubd
psubq
psubsb
psubsw
psubusb
psubusw
psubw
punpckhbw
punpckhdq
punpckhqdq
punpckhwd
punpcklbw
punpckldq
punpcklqdq
punpcklwd
push
pusha
pushad
pushf
pushfd
pxor
rcl
rcpps
rcpss
rcr
rdmsr
rdpmc
rdtsc
rep
repe
repne
repnz
repz
ret
retf
rol
ror
rsm
rsqrtps
rsqrtss
sahf
sal
sar
sbb
scas
scasb
scasd
scasw
seta
setae
setb
setbe
setc
sete
setg
setge
setl
setle
setna
setnae
setnb
setnbe
setnc
setne
setng
setnge
setnl
setnle
setno
setnp
setns
setnz
seto
setp
setpe
setpo
sets
setz
sfence
sgdt
shl
shld
shr
shrd
shufpd
shufps
sidt
sldt
smsw
sqrtpd
sqrtps
sqrtsd
sqrtss
stc
std
sti
stmxcsr
stos
stosb
stosd
stosw
str
sub
subpd
subps
subsd
subss
sysenter
sysexit
test
ucomisd
ucomiss
ud2
unpckhpd
unpckhps
unpcklpd
unpcklps
verr
verw
wait
wbinvd
wrmsr
xadd
xchg
xlat
xlatb
xor
xorpd
xorps
支持的 AMD 操作码pavgusb
pf2id
pfacc
pfadd
pfcmpeq
pfcmpge
pfcmpgt
pfmax
pfmin
pfmul
pfnacc
pfpnacc
pfrcp
pfrcpit1
pfrcpit2
pfrsqit1
pfrsqrt
pfsub
pfsubr
pi2fd
pmulhrw
pswapd