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: ;
pop EBX ;
mov pc[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类型前缀 消除歧义: add byte ptr [EAX],3 ;
add int ptr [EAX],7 ;
结构/联合/类 成员偏移量假设指向聚集的指针位于一个寄存器中,如果要访问聚集的成员,应使用成员的限定名: struct Foo { int a,b,c; }
int bar(Foo *f)
{
asm
{ mov EBX,f ;
mov EAX,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 |

|