当前位置: 首页 > 图文教程 > 操作系统 > Unix/Linux > AT&T x86 asm 语法! for linux kernel

Unix/Linux
Linux 备份 恢复方法
Linux玩CS反恐精英的方法
在一个ISO镜像中集成多个不同的linux发行版,可刻盘,可引导
Linux 快捷键使用
Linux DHCP 服务器配置方法介绍
Linux 22端口的修改方法
Linux 记录会话过程的命令
Linux 后台执行程序如何操作?
linux Wget命令来浏览网页的方法
Linux tail命令的巧妙应用
Wine 中文存在很多的乱码怎么解决方法
linux 新手教程之创建锁文件的方法
配置Linux 保证其系统的安全
Linux DHCP协议实现过程
Linux系统下破解SAM密码
linux/unix vi 编辑器用法详解
Linux 误删文件的解决方法
Linux系统下的历史记录删除方法
Red Hat Linux 安全设置指南
Linux基本命令-注销、关机、重启

Unix/Linux 中的 AT&T x86 asm 语法! for linux kernel


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-01   浏览: 67 ::
收藏到网摘: n/a

创建时间:2001-04-09文章属性:翻译文章提交:e4gle (e4gle_at_hackermail.com)AT&T x86 asm 语法译:el8,alert7 from m4in security teams(www.m4in.org)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 , %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 // movzS和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 , %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_nonzerocx_zero: jmp foocx_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 %eaxn movl , %eaxn popl %eax" );假如你不用到特别的输入输出变量或者修改任何寄存器的值,一般来说是不会使用到其他的三个字段的, 让我们来分析一下输入变量。 int i = 0; __asm__(" pushl %%eaxn movl %0, %%eaxn addl , %%eaxn movl %%eax, %0n popl %%eax" : : "g" (i) ); // increment i不要为上面的代码所困扰! 我将尽力来解释它。我们想让输入变量i加1,我们没有任何输出变量, 也没有改变寄存器值(我们保存了eax值)。 因此,第二个和最后一个字段是空的。 因为指定了输入字段, 我们仍需要保留一个空的输出字段, 但是没有最后一个字段, 因为它没被使用。在两个空冒号之间留下一个新行或者至少一个空格。下面让我们来看看输入字段。 附加描述符可以修正指令来让你给定的编译器来正确处理这些变量。他们一般被附上双引号。 那么这个"g"是用来做什么的呢? 只要是合法的汇编指令,"g"就让编译器决定该在哪里加载i的值。一般来说,你的大部分输入变量都可以被赋予"g", 让编译器决定如何去加载它们 (gcc甚至可以优化它们!)。 其他描述符使用"r" (加载到任何可用的寄存器去), "a" (ax/eax), "b" (bx/ebx), "c" (cx/ecx), "d" (dx/edx), "D" (di/edi), "S" (si/esi), 等等。 我们将要提到一个在asm代码里面的如%0的输入变量。如果我们有两个输入, 他们会一个是%0一个是%1, 在输入段里按顺序排列 (如下一个例子)。假如N个输入变量且没有输出变量, 从%0 到%N-1将和输入字段里的变量相对应, 按顺序排列。 如果任何的输入, 输出, 寄存器修改字段被使用, 汇编代码里的寄存器名必须用两个%来代替一个%。对应于第一个没有使用最后三个字段的例子。让我们看看两个输入变量且引入了"volatile"的例子: int i=0, j=1; __asm__ __volatile__(" pushl %%eaxn movl %0, %%eaxn addl %1, %%eaxn movl %%eax, %0n popl %%eax" : : "g" (i), "g" (j) ); // increment i by jOkay, 现在我们已经有了两个输入变量了。没问题了, 我们只需要记住%0对应第一个输入变量(在