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

Unix/Linux
Linux crontab定时执行任务 命令格式与详细例子
linux 查看用户及用户组的方法
让Linux系统有效防御ARP攻击的实用技巧
Linux 常用软件列表
linux wget 一个强大的下载命令
linux 常用脚本、命令
linux 磁盘配额 简单介绍
Linux服务器架设笔记 Squid服务器配置
ubuntu intel 集成显卡安装
ubuntu 9.04 X3100 显卡开启3D特效
Ubuntu 8.10 Server Ruby 的安装方法
Ubuntu root帐户密码修改
ubuntu下apt-get 命令参数
Ubuntu Linux下实现QQ的三种方式
Ubuntu 8.04中建立PHP+MySQL环境
Ubuntu常用软件大全
Ubuntu系统下安装Aircrack-ng
Ubuntu实现FTP功能
ubuntu 字体美化实现方法
ubuntu下netbeans汉字显示残缺问题

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-01   浏览: 68 ::
收藏到网摘: 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对应第一个输入变量(在