D语言中的内联汇编在x86平台上的实现

来源:互联网 发布:dj软件打碟 编辑:程序博客网 时间:2024/03/29 13:15

D x86 内联汇编

Some Assembly RequiredD,作为一种系统程序设计语言,提供了内联汇编的功能。对于同一个处理器家族来说,D 的内联汇编的实现是标准化了的,例如,Intel Pentium 上的 Win32 D 编译器的内联汇编的语法同 Intel Pentium 上的 Linux D 编译器的语法是一样的。

但是,不同的 D 实现,可以依内存模型、函数调用/返回约定,参数传递约定等的不同而自由实现内联汇编。

本文描述了内联汇编的 x86 实现。

Asm指令:标志符 : Asm指令align 整数表达式evennakeddb 多个操作数ds 多个操作数di 多个操作数dl 多个操作数df 多个操作数dd 多个操作数de 多个操作数操作码操作码 多个操作数多个操作数操作数操作数 , 多个操作数
AsmInstruction:Identifier : AsmInstructionalign IntegerExpressionevennakeddb Operandsds Operandsdi Operandsdl Operandsdf Operandsdd Operandsde OperandsOpcodeOpcode OperandsOperandsOperandOperand , 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:    AsmExpAsmExp:    AsmLogOrExp    AsmLogOrExp ? AsmExp : AsmExpAsmLogOrExp:    AsmLogAndExp    AsmLogAndExp || AsmLogAndExpAsmLogAndExp:    AsmOrExp    AsmOrExp && AsmOrExpAsmOrExp:    AsmXorExp    AsmXorExp | AsmXorExpAsmXorExp:    AsmAndExp    AsmAndExp ^ AsmAndExpAsmAndExp:    AsmEqualExp    AsmEqualExp & AsmEqualExpAsmEqualExp:    AsmRelExp    AsmRelExp == AsmRelExp    AsmRelExp != AsmRelExpAsmRelExp:    AsmShiftExp    AsmShiftExp < AsmShiftExp    AsmShiftExp <= AsmShiftExp    AsmShiftExp > AsmShiftExp    AsmShiftExp >= AsmShiftExpAsmShiftExp:    AsmAddExp    AsmAddExp << AsmAddExp    AsmAddExp >> AsmAddExp    AsmAddExp >>> AsmAddExpAsmAddExp:    AsmMulExp    AsmMulExp + AsmMulExp    AsmMulExp - AsmMulExpAsmMulExp:    AsmBrExp    AsmBrExp * AsmBrExp    AsmBrExp / AsmBrExp    AsmBrExp % AsmBrExpAsmBrExp:    AsmUnaExp    AsmBrExp [ AsmExp ]AsmUnaExp:    AsmTypePrefix AsmExp    offset AsmExp    seg AsmExp    + AsmUnaExp    - AsmUnaExp    ! AsmUnaExp    ~ AsmUnaExp    AsmPrimaryExpAsmPrimaryExp    IntegerConstant    FloatConstant    __LOCAL_SIZE    $    Register    DotIdentifierDotIdentifier    Identifier    Identifier . DotIdentifier
操作数的语法基本遵从了 Intel CPU 文档的约定。具体来说,就是右边的操作数是源操作数,左边的操作数是目的操作数。同 Intel 存在不同之处主要是为了同 D 语言的记号识别器和简单解析的目标兼容。

操作类型

Asm类型前缀:near ptrfar ptrbyte ptrshort ptrint ptrword ptrdword ptrfloat ptrdouble ptrextended ptr
AsmTypePrefix:near ptrfar ptrbyte ptrshort ptrint ptrword ptrdword ptrfloat ptrdouble ptrextended 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 并且手动制定堆栈结构时,这会很方便。

支持的操作码

aaaaadaamaasadcaddaddpdaddpsaddsdaddssandandnpdandnpsandpdandpsarplboundbsfbsrbswapbtbtcbtrbtscallcbwcdqclccldclflushclicltscmccmovacmovaecmovbcmovbecmovccmovecmovgcmovgecmovlcmovlecmovnacmovnaecmovnbcmovnbecmovnccmovnecmovngcmovngecmovnlcmovnlecmovnocmovnpcmovnscmovnzcmovocmovpcmovpecmovpocmovscmovzcmpcmppdcmppscmpscmpsbcmpsdcmpsscmpswcmpxch8bcmpxchgcomisdcomisscpuidcvtdq2pdcvtdq2pscvtpd2dqcvtpd2picvtpd2pscvtpi2pdcvtpi2pscvtps2dqcvtps2pdcvtps2picvtsd2sicvtsd2sscvtsi2sdcvtsi2sscvtss2sdcvtss2sicvttpd2dqcvttpd2picvttps2dqcvttps2picvttsd2sicvttss2sicwdcwdedadaadasdbdddedecdfdidivdivpddivpsdivsddivssdldqdsdtdwemmsenterf2xm1fabsfaddfaddpfbldfbstpfchsfclexfcmovbfcmovbefcmovefcmovnbfcmovnbefcmovnefcmovnufcmovufcomfcomifcomipfcompfcomppfcosfdecstpfdisifdivfdivpfdivrfdivrpfeniffreefiaddficomficompfidivfidivrfildfimulfincstpfinitfistfistpfisubfisubrfldfld1fldcwfldenvfldl2efldl2tfldlg2fldln2fldpifldzfmulfmulpfnclexfndisifnenifninitfnopfnsavefnstcwfnstenvfnstswfpatanfpremfprem1fptanfrndintfrstorfsavefscalefsetpmfsinfsincosfsqrtfstfstcwfstenvfstpfstswfsubfsubpfsubrfsubrpftstfucomfucomifucomipfucompfucomppfwaitfxamfxchfxrstorfxsavefxtractfyl2xfyl2xp1hltidivimulinincinsinsbinsdinswintintoinvdinvlpgiretiretdjajaejbjbejcjcxzjejecxzjgjgejljlejmpjnajnaejnbjnbejncjnejngjngejnljnlejnojnpjnsjnzjojpjpejpojsjzlahflarldmxcsrldslealeaveleslfencelfslgdtlgslidtlldtlmswlocklodslodsblodsdlodswlooploopeloopneloopnzloopzlsllssltrmaskmovdqumaskmovqmaxpdmaxpsmaxsdmaxssmfenceminpdminpsminsdminssmovmovapdmovapsmovdmovdq2qmovdqamovdqumovhlpsmovhpdmovhpsmovlhpsmovlpdmovlpsmovmskpdmovmskpsmovntdqmovntimovntpdmovntpsmovntqmovqmovq2dqmovsmovsbmovsdmovssmovswmovsxmovupdmovupsmovzxmulmulpdmulpsmulsdmulssnegnopnotororpdorpsoutoutsoutsboutsdoutswpackssdwpacksswbpackuswbpaddbpadddpaddqpaddsbpaddswpaddusbpadduswpaddwpandpandnpavgbpavgwpcmpeqbpcmpeqdpcmpeqwpcmpgtbpcmpgtdpcmpgtwpextrwpinsrwpmaddwdpmaxswpmaxubpminswpminubpmovmskbpmulhuwpmulhwpmullwpmuludqpoppopapopadpopfpopfdporprefetchntaprefetcht0prefetcht1prefetcht2psadbwpshufdpshufhwpshuflwpshufwpslldpslldqpsllqpsllwpsradpsrawpsrldpsrldqpsrlqpsrlwpsubbpsubdpsubqpsubsbpsubswpsubusbpsubuswpsubwpunpckhbwpunpckhdqpunpckhqdqpunpckhwdpunpcklbwpunpckldqpunpcklqdqpunpcklwdpushpushapushadpushfpushfdpxorrclrcppsrcpssrcrrdmsrrdpmcrdtscrepreperepnerepnzrepzretretfrolrorrsmrsqrtpsrsqrtsssahfsalsarsbbscasscasbscasdscaswsetasetaesetbsetbesetcsetesetgsetgesetlsetlesetnasetnaesetnbsetnbesetncsetnesetngsetngesetnlsetnlesetnosetnpsetnssetnzsetosetpsetpesetposetssetzsfencesgdtshlshldshrshrdshufpdshufpssidtsldtsmswsqrtpdsqrtpssqrtsdsqrtssstcstdstistmxcsrstosstosbstosdstoswstrsubsubpdsubpssubsdsubsssysentersysexittestucomisducomissud2unpckhpdunpckhpsunpcklpdunpcklpsverrverwwaitwbinvdwrmsrxaddxchgxlatxlatbxorxorpdxorps

支持的 AMD 操作码

pavgusbpf2idpfaccpfaddpfcmpeqpfcmpgepfcmpgtpfmaxpfminpfmulpfnaccpfpnaccpfrcppfrcpit1pfrcpit2pfrsqit1pfrsqrtpfsubpfsubrpi2fdpmulhrwpswapd
原创粉丝点击