汇编基本语法简介

转载 http://www.360doc.com/content/10/0926/12/1317564_56492037.shtml

汇编基本语法简介
在 AT&T 汇编格式中,寄存器名要加上 ‘%‘ 作为前缀;而在 Intel 汇编格式中,寄存器名不需要加前缀。例如:
AT&T 格式
 Intel 格式
 
pushl %eax
 push eax

在 AT&T 汇编格式中,用 ‘$‘ 前缀表示一个立即操作数;而在 Intel 汇编格式中,立即数的表示不用带任何前缀。例如:
AT&T 格式
 Intel 格式
 
pushl $1
 push 1

AT&T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中,目标操作数在源操作数的左边;而在 AT&T 汇编格式中,目标操作数在源操作数的右边。例如:
AT&T 格式
 Intel 格式
 
addl $1, %eax
 add eax, 1

在 AT&T 汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀‘b‘、‘w‘、‘l‘分别表示操作数为字节(byte,8 比特)、字(word,16 比特)和长字(long,32比特);而在 Intel 汇编格式中,操作数的字长是用 "byte ptr" 和 "word ptr" 等前缀来表示的。例如:
AT&T 格式
 Intel 格式
 
movb val, %al
 mov al, byte ptr val

在 AT&T 汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上‘*‘作为前缀,而在 Intel 格式中则不需要。
远程转移指令和远程子调用指令的操作码,在 AT&T 汇编格式中为 "ljump" 和 "lcall",而在 Intel 汇编格式中则为 "jmp far" 和 "call far",即:
AT&T 格式 Intel 格式
ljump $section, $offset
 jmp far section:offset
 
lcall $section, $offset
 call far section:offset

与之相应的远程返回指令则为:
AT&T 格式
 Intel 格式
 
lret $stack_adjust
 ret far stack_adjust

在 AT&T 汇编格式中,内存操作数的寻址方式是
AT&T 格式
 Intel 格式
 
section:disp(base, index, scale)
 section:[base + index*scale + disp]

由于 Linux 工作在保护模式下,用的是 32 位线性地址,所以在计算地址时不用考虑段基址和偏移量,而是采用如下的地址计算方法:disp + base + index * scale
下面是一些内存操作数的例子:
AT&T 格式
 Intel 格式
 
movl -4(%ebp), %eax
 mov eax, [ebp - 4]
 
movl array(, %eax, 4), %eax
 mov eax, [eax*4 + array]
 
movw array(%ebx, %eax, 4), %cx
 mov cx, [ebx + 4*eax + array]
 
movb $4, %fs:(%eax)
 mov fs:eax, 4

内嵌汇编格式简介
内嵌汇编语法如下:
__asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分)

其中,asm 和 __asm__是完全一样的。共四个部分:汇编语句模板,输出部分,输入部分,破坏描述部分,各部分使用“:”格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。例如:
__asm__ __volatile__("cli": : :"memory")

1、汇编语句模板
    汇编语句模板由汇编语句序列组成,语句之间使用 “;”、“\\n”或“\\n\\t”分开。指令中的操作数可以使用占位符引用C语言变量,操作数占位符最多10个,名称如下:%0,%1,…,%9。指令中使用占位符表示的操作数,总被视为long型(4个字节),但对其施加的操作根据指令可以是字或者字节,当把操作数当作字或者字节使用时,默认为低字或者低字节。对字节操作可以显式的指明是低字节还是次字节。方法是在%和序号之间插入一个字母,“b”代表低字节,“h”代表高字节,例如:%h1。
 
2、输出部分
    输出部分描述输出操作数,不同的操作数描述符之间用逗号格开,每个操作数描述符由限定字符串和C 语言变量组成。每个输出操作数的限定字符串必须包含“=”表示他是一个输出操作数。
例:
__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x) )

描述符字符串表示对该变量的限制条件,这样GCC 就可以根据这些条件决定如何分配寄存器,如何产生必要的代码处理指令操作数与C表达式或C变量之间的联系。
 
3、输入部分
输入部分描述输入操作数,不同的操作数描述符之间使用逗号格开,每个操作数描述符由限定字符串和C语言表达式或者C语言变量组成。
例1 :
__asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));

例二(bitops.h):
Static __inline__ void __set_bit(int nr, volatile void * addr)
{
        __asm__(
                         "btsl %1,%0"
                        :"=m" (ADDR)
                        :"Ir" (nr));
}

后例功能是将(*addr)的第nr位设为 1。第一个占位符%0与C 语言变量ADDR对应,第二个占位符%1与C语言变量nr对应。因此上面的汇编语句代码与下面的伪代码等价:btsl nr, ADDR,该指令的两个操作数不能全是内存变量,因此将nr的限定字符串指定为“Ir”,将nr 与立即数或者寄存器相关联,这样两个操作数中只有ADDR为内存变量。
 
4、限制字符
   4.1、限制字符列表
   限制字符有很多种,有些是与特定体系结构相关,此处仅列出常用的限定字符和i386中可能用到的一些常用的限定符。它们的作用是指示编译器如何处理其后的C语言变量与指令操作数之间的关系。
分类
 限定符
 描述
 
 
 
 
 
 
 
 
通用寄存器
 a
 将输入变量放入eax这里有一个问题:假设eax已经被使用,那怎么办?其实很简单:因为GCC 知道eax 已经被使用,它在这段汇编代码的起始处插入一条语句pushl %eax,将eax 内容保存到堆栈,然后在这段代码结束处再增加一条语句popl %eax,恢复eax的内容
 
b
 将输入变量放入ebx
 
c
 将输入变量放入ecx
 
d
 将输入变量放入edx
 
s
 将输入变量放入esi
 
d
 将输入变量放入edi
 
q
 将输入变量放入eax,ebx,ecx,edx中的一个
 
r
 将输入变量放入通用寄存器,也就是eax,ebx,ecx,edx,esi,edi中的一个
 
A
 把eax和edx合成一个64 位的寄存器(use long longs)
 
 
 
 
内存
 m
 内存变量
 
o
 操作数为内存变量,但是其寻址方式是偏移量类型,也即是基址寻址,或者是基址加变址寻址
 
V
 操作数为内存变量,但寻址方式不是偏移量类型
 
“”
 操作数为内存变量,但寻址方式为自动增量
 
p
 操作数是一个合法的内存地址(指针)
 
寄存器或内存
 g
 将输入变量放入eax,ebx,ecx,edx中的一个或者作为内存变量
 
X
 操作数可以是任何类型
 
 
 
 
立即数
 I
 0-31之间的立即数(用于32位移位指令)
 
J
 0-63之间的立即数(用于64位移位指令)
 
N
 0-255之间的立即数(用于out指令)
 
i
 立即数
 
n
 立即数,有些系统不支持除字以外的立即数,这些系统应该使用“n”而不是“i”
 
 
 
匹配
 0
 表示用它限制的操作数与某个指定的操作数匹配,
 
1
 也即该操作数就是指定的那个操作数,例如“0”
 
9
 去描述“%1”操作数,那么“%1”引用的其实就是“%0”操作数,注意作为限定符字母的0-9 与指令中的“%0”-“%9”的区别,前者描述操作数,后者代表操作数。
 
 &
 该输出操作数不能使用过和输入操作数相同的寄存器
 
 
操作数类型
 =
 操作数在指令中是只写的(输出操作数)
 
+
 操作数在指令中是读写类型的(输入输出操作数)
 
 
 
 
 
浮点数
 f
 浮点寄存器
 
t
 第一个浮点寄存器
 
u
 第二个浮点寄存器
 
G
 标准的80387浮点常数
 
%
 该操作数可以和下一个操作数交换位置 例如addl的两个操作数可以交换顺序(当然两个操作数都不能是立即数)
 
#
 部分注释,从该字符到其后的逗号之间所有字母被忽略
 
*
 表示如果选用寄存器,则其后的字母被忽略

5、破坏描述部分
   破坏描述符用于通知编译器我们使用了哪些寄存器或内存,由逗号格开的字符串组成,每个字符串描述一种情况,一般是寄存器名;除寄存器外还有“memory”。例如:“%eax”,“%ebx”,“memory”等。
感谢
这篇文章是两篇文章的综合体,我只是把这两篇文章综合起来了,进行了一下简单的排版,阅读起来方便一点,舒服一点。两位作者分别是肖文鹏和临江仙,向他们表示感谢。后续我会根据相关资料,继续改进该文档,使之更全面。Mail:[email protected],互相学习。

时间: 2024-10-26 19:13:25

汇编基本语法简介的相关文章

Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)

在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly.本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^). 注意:由于gcc采用AT&T风格的汇编语法(与Intel Syntax相对应,二者的区别参见这里),因此,本文涉及到的汇编代码均以AT&T Syntax为准. 1. 基本语法规则 内联汇编(或称嵌入汇

MarkDown语法简介

Markdown 语法简介 概述 宗旨 兼容 HTML 特殊字符自动转换 区块元素 段落和换行 标题 区块引用 列表 代码区块 分隔线 区段元素 链接 强调 代码 图片 其它 反斜杠 自动链接 感谢 Markdown 免费编辑器 概述 宗旨 Markdown 的目标是实现「易读易写」. 可读性,无论如何,都是最重要的.一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布,并且看起来不会像是由许多标签或是格式指令所构成.Markdown 语法受到一些既有 text-to-HTML 格

freemarker语法简介

ftl是一种模板标记语言,用于渲染数据,输入html结构.语法简介如下: ${book.name} ${book.name?if_exists} //值是否存在 ${book.name??} //值是否存在 ${book.name?has_content} //值是否存在 ${book.name?default("xxx")} //默认值xxx ${book.name!"xxx"} //默认值xxx ${book.date?string("yyyy-mm-

Razor基础语法简介

原文:Razor基础语法简介 Razor的出现,使页面看起更加简洁,Razor的页面后缀为:.cshtmlRazor基础语法:1.代码注释:      多行注释: @*注释信息*@     单行注释: // 注释 1.代码体{...} @{ var x=100; var y=100; string str="this is string": } 在代码体中,没一行都需要用";"结束,代码区中,字母区分大小写.字符类型常量必须用""括起来,2. 由

Android系统Recovery工作原理之使用update.zip升级过程---updater-script脚本语法简介以及执行流程(转)

目前update-script脚本格式是edify,其与amend有何区别,暂不讨论,我们只分析其中主要的语法,以及脚本的流程控制. 一.update-script脚本语法简介: 我们顺着所生成的脚本来看其中主要涉及的语法. 1.assert(condition):如果condition参数的计算结果为False,则停止脚本执行,否则继续执行脚本. 2.show_progress(frac,sec):frac表示进度完成的数值,sec表示整个过程的总秒数.主要用与显示UI上的进度条. 3.for

perl语法简介

Perl语法简介 1.PERL变量 1.1.Perl变量分类 1.2.Perl变量 1.2.1 Scalar变量 1.2.2 数组变量 1.2.3 标量与数组变量 1.2.4 关联数组 2.PERL运算符 2.1 算数运算符 2.2 位运算符 2.3 比较运算符 2.4 逻辑运算符 2.5 字符运算符 2.6 赋值运算符 2.7 Lvalue 2.8 表运算符 2.9 文件测试运算符 1.PERL变量 1.1.Perl变量分类 Perl变量分为标量变量,数组变量,关联数组变量3类.PERL的变量

【ABAP系列】SAP ABAP7.40新语法简介第一篇

公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP7.40新语法简介第一篇 前言部分 大家可以关注我的公众号,公众号里的排版更好,阅读更舒适. 正文部分 SAP的系统不断的更新 7.40已经出来很久了,一直忙着没有更新7.40新语法内容 慢慢写点新语法的相关内容 首先说一下7.40的特点及简介 1.ABAP 7.40是AS ABAP 7.31(也称为ABAP 7.

C编译器剖析_6.1 汇编代码生成_简介

6.1 汇编代码生成简介 历经词法分析.语法分析.语义检查和中间代码生成阶段,我们终于来到了"目标代码生成阶段",由于UCC编译器的目标代码即为32位x86汇编代码,因此我们就把本章称为"汇编代码生成".UCC编译器中的大部分源代码都适用于Windows和Linux平台,但Windows平台上缺省的汇编器支持Intel风格的x86汇编代码,而Linux平台默认的汇编器则采用AT&T风格的x86汇编代码,两者在汇编语法上有一些差别,为节省篇幅,我们主要针对Li

[转载]【Linux学习笔记】Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)

在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly.本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^).        注意:由于gcc采用AT&T风格的汇编语法(与Intel Syntax相对应,二者的区别参见这里),因此,本文涉及到的汇编代码均以AT&T Syntax为准. 1. 基本语法规则