Linux中的汇编简介
GNU as汇编语法
GNU汇编语法使用的是AT&T汇编它和Intel汇编的语法主要有以下一些不同:
- AT&T汇编中的立即操作数前面要加上'$',寄存器操作数名前要加上百分号'%',绝对跳转操作数前要加上'*',Intel的语法均不包含这些符号;
- AT&T语法与Intel语法中使用的源操作数和目的操作数顺序正好相反,AT&T的源操作数和目的操作数是从左到右,Intel语法是从右到左,例如add eax, 4在AT&T语法中是addl $4, %eax;
- AT&T语法中内存操作数长度由操作码的最后一位字符来确定,操作码后缀有b/w/l分别代表内存引用宽度为8位,16位和32位,Intel语法则通过在内存操作数前使用前缀byte ptr,word ptr和dword ptr来达到此目的。例如Intel中的mov al, byte ptr foo对应AT&T中的语句为movb $foo, %al;
- AT&T语法中立即跳转和调用为ljmp/lcall $section, $offset,而Intel中的是jmp/call far section:offset,AT&T中的返回指令lret $stack-adjust对应Intel的ret far stack-adjust;
- AT&T汇编器不支持多代码段程序,类UNIX系统要求所有代码在一个段中;
预处理:as汇编器能对汇编语言进行简单的预处理,包括删除多余的空格和制表符,删除注释语句,把字符常数转换为对应的数值,但此预处理不能处理宏,也没有处理包含文件的功能,如果需要这些功能,可以使用gcc的预处理器cpp来实现。
符号:GNU汇编语言中的符号是由字符组成的标识符,组成符号的字符包含大小写字母,数字和_.$三个字符,符号不允许以数字开始,且区分大小写。在汇编程序中符号长度没有限制,符号使用空格来界定开始和结束。语句以换行符或者行分割符(;)作为结束,文件最后必须以换行符作为结束,语句有0个或多个标号开始(Label),后面可跟随一个确定语句类型的关键符号,标号由符号后面跟随一个冒号构成,关键符号确定了余下部分语句的语义,如果关键符号以.开始,那么当前语句就是一个汇编命令,如果关键符号以字母开始,那么当前语句就是一条汇编语言指令语句,一it哦啊语句的通用格式为:
标号:汇编命令 注释语句
或者
标号:指令助记符 操作数1, 操作数2 注释语句
常数:常数是一个数字,分为字符常数和数字常数两类,字符常数分为单个字符和字符串,数字常数分为整数和浮点数。汇编语言的单个字符表示一版为在该字符前加上单引号,而字符串需要添加双引号。
指令:指令是CPU执行的操作,通常指令称为操作码,操作数是指令操作的对象,而地址是指令数据在内存中的位置,一条指令语句一版包括:标号,操作码(指令助记符),操作数,注释。
操作数:操作数包含立即操作数,寄存器和内存。间接操作数含有实际操作数的地址值,AT&T语法通过在操作数前加上*来表示间接操作数,只有跳转和调用指令才能使用间接操作数。立即操作数前面需要加上$符号,寄存器名前面需要加上%符号,内存操作数由变量名或者含有变量地址的寄存器指定,变量名隐含指出了变量的地址,并指示cpu引用改地址内存处的内容。
操作码:AT&T语法中指令操作码最后一个字符用来指明操作数的宽度,字符b,w和l分别制定byte,word和long类型的操作数。如果指令名没有带字符后缀,并且指定语句中不含内存操作数,那么as汇编器会根据寄存器操作数来尝试确定操作数宽度。操作码前缀用于修饰随后的操作码,他们用于重复字符串指令,提供区覆盖,执行总线锁定操作或者指定操作数和地址宽度。
内存引用:AT&T语法的间接内存引用形式为section:disp(base, index, scale),其中base和index是32位的基寄存器和索引寄存器,disp是可选的偏移值,scale是比例因子,scale乘上index用来表示操作数地址,section为内存操作数指定的段寄存器。
movl var, %eax #把内存地址var处的内容放入寄存器%eax
movl %cs:var, %eax #把代码段中的内存地址var处的内容放入%eax
movb $0xa0, %es:(%ebx) #把0xa0放入到es段的%ebx指定的偏移处
movl $var, %eax #把var的地址放入%eax
movl array(%esi), %eax #把array+%esi内存地址的内容放入eax
movl (%ebx, %esi, ), %eax #把ebx+esi*4地址处的内容放到eax
movl array(%ebx, %esi, ), %eax#把array+ebx+esi*4地址的内容放到eax
movl -(%ebp), %eax #把ebp-4地址处的内容放到eax
指令跳转:跳转指令用于把执行点转移到程序的另外的位置执行,跳转的目的位置通常用一个标号来表示。jmp是无条件跳转,可分为直接跳转和间接跳转,直接跳转语句的写法是给出跳转目标处的标号,间接跳转语句的写法是使用*作为操作指示符的前缀字符。
段:段用于表示一个地址范围,它主要用来表示编译器生成的目标文件中的不同的信息区域。例如代码段,数据段,bss段。
符号:符号有很多作用,可以用来命名对象,连接器通过符号执行链接操作,调试器利用符号进行调试。标号是后面接着一个冒号的符号,该符号用来表示代码当前的位置。特殊符号.用来表示汇编的当前位置。除了名字之外每个符号都有值和类型属性。符号的值通常是32位的,链接器会对未定义的符号值做特殊处理,如果未定义的符号值为0则表示该符号在此汇编程序中没有定义,链接器会尝试使用其他链接的文件来确定此符号值,
as汇编器
as汇编器的命令行格式为: as [选项] [-o objfile] [srcfile.s],如果没有指定输出文件名,会默认输出a.out文件。可以再as命令行上给出0个或多个输入文件名,as会按照从左到右的顺序读取这些文件中的内容,在命令行上的参数如果没有实际意义将会被当做输入文件名看待,如果命令行上没有任何文件名,那么as将会试图从终端读取输入文件内容。
as的输出文件:由输入的汇编文件编译生成的二进制文件,目标文件最终作为连接器ld的输入文件。目标文件中包含汇编代码,协助ld产生可执行文件的信息,以及用于调试的符号信息。
内联汇编
内联汇编的基本格式为:
asm("汇编语句"
: 输出寄存器
: 输入寄存器
: 会被修改的寄存器)
除了汇编语句是必须的的以外,其他若不使用都可以省略。其中asm是内联汇编的关键词,汇编语句用于编写汇编指令,输出寄存器表示当这段汇编语句执行完之后,哪些寄存器用于存放输出数据,输入寄存器表示开始执行代码时,制定某些寄存器中应该放入的输入值,会被修改的寄存器表示对列出的寄存器中的值进行了修改。
常用的寄存器加载代码
代码 | 说明 | 代码 | 说明 |
a | 使用寄存器eax | m | 使用内存地址 |
b | 使用寄存器ebx | o | 使用内存地址并且可以加偏移值 |
c | 使用寄存器ecx | I | 使用常数0~31 |
d | 使用寄存器edx | J | 使用常数0~63 |
S | 使用esi | K | 使用常数0~255 |
D | 使用edi | L | 使用常数0~65535 |
q | 使用动态分配字节可寻址寄存器 | M | 使用常数0~3 |
r | 使用任意动态分配寄存器 | N | 使用1字节常数 |
g | 使用通用有效地址 | O | 使用常数0~31 |
A | 使用eax和edx联合 | = | 输出操作数,输出值替换前值 |
+ | 表示操作数可读可写 | & | 在使用完操作数之前内容会被修改 |
在执行代码时,如果不希望汇编语句被gcc优化,需要在asm符号后面添加关键字volatile。关键字volatile也可以放在函数名前来修饰函数,用来通知gcc该函数不会返回。
Linux中的汇编简介的更多相关文章
- Linux中Mysql的简介和安装
MySQL 简介 点击查看MySQL官方网站 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,后来被Sun公司收购,Sun公司后来又被Oracle公司收购,目前属于Oracle旗 ...
- linux中的信号简介和trap命令
1.信号 linux通过信号来在运行在系统上的进程之间通信,也可以通过信号来控制shell脚本的运行 主要有一下信号 1 ##进程重新加载配置 2 ##删除进程在内存中的数据 3 ##删除鼠标在内存中 ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- Linux 中 x86 的内联汇编
工程中需要用到内联汇编,找到一篇不错的文章,趁机学习下. 原文地址:http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/ 如果 ...
- linux中的strings命令简介2
摘自:http://blog.csdn.net/stpeace/article/details/46641069 linux中的strings命令简介 之前我们聊过linux strings的用法和用 ...
- linux中的strings命令简介
摘自:http://blog.csdn.net/stpeace/article/details/46641069 linux中的strings命令简介 在linux下搞软件开发的朋友, 几乎没有不知道 ...
- Linux中的IO复用接口简介(文件监视?)
I/O复用是Linux中的I/O模型之一.所谓I/O复用,指的是进程预先告诉内核,使得内核一旦发现进程指定的一个或多个I/O条件就绪,就通知进程进行处理,从而不会在单个I/O上导致阻塞. 在Linux ...
- LInux内核分析--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验者:江军 ID:fuchen1994 实验描述: 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3 ...
- linux内核分析第四周-使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
本周作业的主要内容就是采用gcc嵌入汇编的方式调用system call.系统调用其实就是操作系统提供的服务.我们平时编写的程序,如果仅仅是数值计算,那么所有的过程都是在用户态完成的,但是我们想将变量 ...
随机推荐
- IFE 百度前端技术学院 2016年春季班作业 第一阶段任务(1-4)的总结
具体任务详细介绍可参考http://ife.baidu.com/task/all 具体代码参考:https://github.com/sunshineqt/webxt/tree/master/stag ...
- 定向转发和重定向实现 <select >下拉表单数据传送
定向转发的特点: (1). 实行转发时浏览器上的网址不变 (如果你这点忽视了,那你就要接受我无尽的鄙视吧! 哇咔咔~~~) (2). 实行转发时 : 只有一次请求. 不信,看这下面的 ...
- OC 实例变量(Instance Var)和成员变量(member var)区别
摘要: Objective-C 引入了“实例变量"的概念,但同时, 也经常出现 “成员变量”的声音. 到底什么是实例变量,什么是成员变量,二者的区别是什么呢? 今天查看apple 的官方 ...
- 转--CSS选择器详解(一)常用选择器
今天复习一下CSS的知识,看了篇文章觉得很好,转来备用. 转自:http://www.cnblogs.com/fattydoit/p/3492028.html 目录 类型选择器 类选择器 ID选择器 ...
- Spring源码学习-PropertyPlaceholderHelper
转载:http://my.oschina.net/ydsakyclguozi/blog/465526 1. CustomPropertyConfigurer.java package property ...
- 网站开发中必备的8个 jQuery 效果【附源码】
jQuery 作为最优秀 JavaScript 库之一,改变了很多人编写 JavaScript 的方式.它简化了 HTML 文档遍历,事件处理,动画和 Ajax 交互,而且有成千上万的成熟 jQuer ...
- iOS --- 通过openURL实现APP之间跳转并传递数据
在IOS中,实现一个应用启动另外一个应用,使用UIApplication的openURL:方法就可实现,这里以test跳到test02为例.(需要先创建这两个工程) 注册自定义URL协议(在test中 ...
- web开发-服务器Controller到前端中的数据传递
一, ajax方式 (一)controller中 1. 定义AjaxResponse类 成员有: status , message, data. 其中 status是成功或失败状态, message ...
- 开始→运行(cmd)命令大全
gpedit.msc-----组策略 sndrec32-------录音机 Nslookup-------IP地址侦测器 explorer-------打开资源管理器 logoff---------注 ...
- django.test.client 使用随记
import os,sys,django; sys.path.append("\\path\\to\\mysite")#ATTETION!,Err: "unable to ...