DJGPP使用AT&T格式的汇编语法,和一般的intel格式的语法有点不同。主要不同点如下:
AT&T语法颠倒了源和目的操作数的位置, 目的操作数在源操作数之后。寄存器操作数要有个%的前缀,立即数操作数要有个$符号的前缀。存储器操作数的大小取决于操作码的最后一个字符。 它们是b(8-bit), w(16-bit)和l(32-bit)。
这里有一些例子。左边部分是at&t格式,右边是intel指令格式。
movw %bx, %ax// mov ax, bx
xorl %eax, %eax// xor eax, eax
movw $1, %ax// mov ax,1
movb X, %ah// mov ah, byte ptr X
movw X, %ax// mov ax, Word ptr X
movl X, %eax// mov eax, X
大部分操作指令,at&t和intel都是差不多的,除了这些:
movsSD // movsx
movzSD // movz
S和D分辨代表源和目的操作数后缀。
movswl %ax, %ecx// movsx ecx, ax
cBTw // cbw
cwtl // cwde
cwtd // cwd
cltd // cdq
lcall $S,$O // call far S:O
ljmp $S,$O // jump far S:O
lret $V // ret far V
操作嘛,前缀不能与它们作用的指令写在同一行。例如rep和stosd应该是两个相互独立的指令, 存储器的情况也有一点不同。通常intel格式的如下:
section:[base + index*scale + disp]
被写成:
section:disp(base, index, scale)
这里有些例子:
movl 4(%ebp), %eax // mov eax, [ebp+4])
addl (%eax,%eax,4), %ecx // add ecx, [eax + eax*4])
movb $4, %fs:(%eax) // mov fs:eax, 4)
movl _array(,%eax,4), %eax // mov eax, [4*eax + array])
movw _array(%ebx,%eax,4), %cx// mov cx, [ebx + 4*eax + array])
Jump 指令通常是个短跳转。可是, 下面这些指令都是只能在一个字节的范围内跳转: jcxz,jecxz,loop,loopz,loope,loopnz和loopne。象在线文档所说的那样,一个jcxz foo可以扩展成以下工作:
jcxz cx_zero
jmp cx_nonzero
cx_zero:
jmp foo
cx_nonzero:
文档也注意到了mul和imul指令。 扩展的乘法指令只用一个操作数,例如, imul $ebx, $ebx将不会把结果放入edx:eax。使用imul %ebx中的单操作数来获得扩展结果。