WEB开发网
开发学院软件开发汇编语言 AT&T x86 asm语法 阅读

AT&T x86 asm语法

 2009-10-12 09:36:39 来源:WEB开发网   
核心提示:DJGPP 使用AT&T格式的汇编语法,和一般的intel格式的语法有点不同,AT&T x86 asm语法,主要不同点如下:AT&T 语法颠倒了源和目的操作数的位置, 目的操作数在源操作数之后,寄存器操作数要有个%的前缀, 立即数操作数要有个$符号的前缀,第二个和最后一个字段是空的, 因为指定了输入字段, 我们

DJGPP 使用AT&T格式的汇编语法。和一般的intel格式的语法有点不同。主要不同点如下:

AT&T 语法颠倒了源和目的操作数的位置, 目的操作数在源操作数之后。寄存器操作数要有个%的前缀, 立即数操作数要有个$符号的前缀。 存储器操作数的大小取决于操作码的最后一个字符。 它们是b (8-bit), w (16-bit), 和 l (32-bit).

这里有一些例子。 左边部分是intel指令格式,右边是at&t格式。

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中的单操作数来获得扩展结果。

Inline Asm

我将首先开始inline asm, 因为似乎关于这方面的疑问非常多。这是最基本的语法了, 就象在线帮助信息中描述的:

__asm__(asm statements : outputs : inputs : reGISters-modified);

这四个字段的含义是:

asm statements - AT&T 的结构, 每新行都是分开的。
outputs - 修饰符一定要用引号引起来, 用逗号分隔
inputs - 修饰符一定要用引号引起来, 用逗号分隔
registers-modified - 名字用逗号分隔
一个小小的例子:
__asm__("
pushl %eax\n
movl $1, %eax\n
popl %eax"
);

假如你不用到特别的输入输出变量或者修改任何寄存器的值,一般来说是不会使用到其他的三个字段的,

让我们来分析一下输入变量。

int i = 0;
__asm__("
pushl %%eax\n
movl %0, %%eax\n
addl $1, %%eax\n
movl %%eax, %0\n
popl %%eax"
:
: "g" (i)
); // increment i

不要为上面的代码所困扰! 我将尽力来解释它。我们想让输入变量i加1,我们没有任何输出变量, 也没有改变寄存器值(我们保存了eax值)。 因此,第二个和最后一个字段是空的。 因为指定了输入字段, 我们仍需要保留一个空的输出字段, 但是没有最后一个字段, 因为它没被使用。在两个空冒号之间留下一个新行或者至少一个空格。

1 2 3  下一页

Tags:AT amp asm

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接