发新话题
打印

26 D语言x86 内联汇编 D x86 Inline Assembler

26 D语言x86 内联汇编 D x86 Inline Assembler

知识若不分享 实在没有意义 http://www.d-programming-language-china.org 20070425

点击下面网址查看原文:
http://www.d-programming-language-china.org

by: uFramer D语言论坛 http://www.d-programming-language-china.org
from: http://www.digitalmars.com/d/iasm.html
version: 基于D 1.013 (Apr 19, 2007)

D,作为一种系统程序设计语言,提供了内联汇编的功能。对于同一个处理器家族来说,D 的内联汇编的实现是标准化了的,例如,Intel Pentium 上的 Win32 D 编译器的内联汇编的语法同 Intel Pentium 上的 Linux D 编译器的语法是一样的。
但是,不同的 D 实现,可以依内存模型、函数调用/返回约定,参数传递约定等的不同而自由实现内联汇编。

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

QUOTE:
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

Labels标号

汇编指令可以象其他语句一样带有标号。它们可以作为 goto 语句的目标。例如:

void *pc;
asm
{
    call L1        ;
 L1:            ;
    pop    EBX        ;
    mov    pc[EBP],EBX    ;    // pc 现在指向 L1 处的代码
}

align IntegerExpressionalign 整数表达式

汇编器使用 NOP 指令进行填充,使下一条指令对齐到 整数表达式 边界上。整数表达式 的值必须是 2 的幂。
使循环代码对齐可以使得执行速度得到可观的提升。

even

汇编器使用 NOP 指令进行填充,使下一条指令对齐到偶数边界上。

nakednaked

禁止编译器生成函数的建帧和退帧指令。这就意味着责任落到了使用内联汇编的程序员的头上,因此这种用法主要用于那些全部用内联汇编编写的函数。( 本文出处: http://www.d-programming-language-china.org )

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;    // insert bytes 0x05, 0x06, and 0x83 into code
    ds 0x1234;    // insert bytes 0x34, 0x12
    di 0x1234;    // insert bytes 0x34, 0x12, 0x00, 0x00
    dl 0x1234;    // insert bytes 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    df 1.234;    // insert float 1.234
    dd 1.234;    // insert double 1.234
    de 1.234;    // insert real 1.234
    db "abc";    // insert bytes 0x61, 0x62, and 0x63
    ds "abc";    // insert bytes 0x61, 0x00, 0x62, 0x00, 0x63, 0x00
}

Opcodes操作码

本文末尾列出了支持的操作码。
支持下面的寄存器。寄存器名都是大写的。

A list of supported opcodes is at the end.
The following registers are supported. Register names are always in upper case.

QUOTE:
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
XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7

1 Special Cases

1.1 lock, rep, repe, repne, repnz, repz

这些前缀指令不能同它们修饰的指令位于同一语句,它们必须单独写成一条指令。例如:( 本文出处: http://www.d-programming-language-china.org )

asm
{
    rep    ;
    movsb ;
}

1.2 pause

内联汇编不支持该操作码,使用( 本文出处: http://www.d-programming-language-china.org )

{
    rep    ;
    nop    ;
}

代替,效果是相同的。

1.3 floating point ops

浮点运算
使用指令的两操作数形式:

fdiv ST(1);    // 错误
fmul ST;        // 错误
fdiv ST,ST(1);    // 正确
fmul ST,ST(0);    // 正确

Operands操作

QUOTE:
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 语言的记号识别器和简单解析的目标兼容。

1 Operand Types操作类型

QUOTE:
AsmTypePrefix:
    near ptr
    far ptr
    byte ptr
    short ptr
    int ptr
    word ptr
    dword ptr
    float ptr
    double ptr
    real ptr

对于操作数大小模棱两可的情况,如同:

add    [EAX],3        ;

可以使用 Asm类型前缀 消除歧义:( 本文出处: http://www.d-programming-language-china.org )

add    byte ptr [EAX],3    ;
add    int ptr [EAX],7    ;

2 Struct/Union/Class Member Offsets结构/联合/类 成员偏移量

假设指向聚集的指针位于一个寄存器中,如果要访问聚集的成员,应使用成员的限定名:

struct Foo { int a,b,c; }
int bar(Foo *f)
{
    asm
    {    mov    EBX,f        ;
    mov    EAX,Foo.b[EBX]    ;
    }
}

3 Special Symbols特殊符号

1.1 $$

代表下一条指令的开始地址。所以,

jmp    $    ;

会跳转到 jmp 后的那条指令处。

1.2 __LOCAL_SIZE

它的值会被局部堆栈帧中的局部字节数替代。当使用 naked 并且手动制定堆栈结构时,这会很方便。

Opcodes Supported支持的操作码

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

1 Pentium 4 (Prescott) Opcodes Supported

addsubpd addsubps fisttp haddpd haddps
hsubpd hsubps lddqu monitor movddup
movshdup movsldup mwait

2 AMD Opcodes Supported

pavgusb pf2id pfacc pfadd pfcmpeq
pfcmpge pfcmpgt pfmax pfmin pfmul
pfnacc pfpnacc pfrcp pfrcpit1 pfrcpit2
pfrsqit1 pfrsqrt pfsub pfsubr pi2fd
pmulhrw pswapd
( lastupdate:20070426 最新文章请访问http://www.d-programming-language-china.org )

关于一大步成功社区:
yidabu提倡在交流中学习,在分享中提高
收集感兴趣的知识,写下心得,通过网络与别人一起分享
理解一点就实践一步,收获什么就分享什么,成功就是这样一点点一步步累积起来的
网络只是一个工具,只有自己身心提高才是实实在在的。d-programming-language-china.org为大家提供一个学习交流各种知识的平台

TOP

发新话题