ins.luhannews.cn

一、简单的汇编程序

以下面这段简单的汇编代码为例

.section .data
.section .text
.globl _start
_start:
movl $, %eax
movl $, %ebx
int $0x80

(注意是globl不是global;movl(MOVL)不是mov1(MOV一))

将这段程序保存为demo.s,然后用汇编器as把汇编程序中的助记符翻译成机器指令(汇编指令与机器指令是对应的)生成目标文件demo.o。然后用链接器ld把目标文件demo.o链接成可执行文件demo(虽然只有一个目标文件但是也需要经过链接才能成为可执行文件因为链接器要修改目标文件中的一些信息)。这个程序只做了一件事就是退出,退出状态为4。shell中可以echo $?得到上一条命令的退出状态。

aaarticlea/png;base64,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" alt="" />

【解释】:汇编程序中以"."开头的名称不是指令的助记符,不会被翻译成机器指令,而是给汇编器一些特殊的指示,称为汇编指示或伪操作。

.section .data
.section .text

.section指示把代码划分成若干个段(section),程序被操作系统加载时,每个段被加载到不同的地址,具有不同的读写执行权限。

.data段保存程序的数据是可读写的,C程序的全局变量也属于.data段。上边的程序没定义数据所以.data是空的。

.text段保存代码,是只读和可执行的,后面那些指令都属于这个.text段。

.globl  _start

_start是一个符号(Symbol),符号在汇编程序中代表一个地址,可以用在指令中,汇编程序经过汇编器的处理后所有的符号都被替换成它所代表的地址值。在C中我们可以通过变量名访问一个变量,其实就是读写某个地址的内存单元,我们通过函数名调用一个函数其实就是调转到该函数的第一条指令所在的地址,所以变量名和函数名都是符号,本质上是代表内存地址的。

.globl指示告诉汇编器_start这个符号要被链接器用到,所以要在目标文件的符号表中给它特殊标记。_start就像C程序的main函数一样特殊是整个程序的入口,链接器在链接时会查找目标文件中的_start符号代表的地址,把它设置为整个程序的入口地址,所以每个汇编程序都要提供一个_start符号并且用.globl声明。如果一个符号没有用.globl指示声明这个符号就不会被链接器用到。

_start:

_start在这里就像C语言的语句标号一样。汇编器在处理汇编程序时会计算每个数据对象和每条指令的地址,当汇编器看到这样一个标号时,就把它下面一条指令的地址作为_start这个符号所代表的地址。而_start这个符号又比较特殊事整个程序的入口地址,所以下一条指令movl $1, %eax就成了程序中第一条被执行的指令。

movl $, %eax

这是一条数据传送指令,CPU内部产生一个数字1, 然后传送到eax寄存器中。mov后边的l表示long,说明是32位的传送指令。CPU内部产生的数称为立即数,在汇编程序中立即数前面加"$"寄存器前面加"%",以便跟符号名区分开。

movl $, %ebx

与上条指令类似,生成一个立即数4,传送到ebx寄存器中。

int $0x80

前两条指令都是为这条指令做准备的,执行这条指令时:

  1. int指令称为软中断指令,可以用这条指令故意产生一个异常。异常的处理与中断类似,CPU从用户模式切换到特权模式,然后跳转到内核代码中执行异常处理程序。

  2. int指令中的立即数0x80是一个参数,在异常处理程序中根据这个参数决定如何处理,在linux内核中,int $0x80这种异常称系统调用(System Call)。内核提供了许多系统服务供用户程序使用,但这些系统服务不能像库函数(比如printf)那样调用,因为在执行用户程序时CPU处于用户模式不能直接调用内核函数,所以需要通过系统调用切换CPU模式,通过异常处理程序进入内核,用户程序只能通过寄存器传几个参数,之后就要按内核设计好的代码路线走,而不能由用户程序随心所欲想调那个内核函数,这样保证了系统服务被安全的调用,在调用结束后CPU再切换回用户模式,继续执行int指令后面的指令,在用户程序看来就像函数的调用和返回一样。

  3. eax和ebx寄存器的值是传递给系统调用的两个参数,eax的值是系统调用号,1表示_exit系统调用,ebx的值则是传给_exit系统调用的参数,也就是退出状态。_exit这个系统调用会终止掉当前进程,而不会返回它继续执行。不同的系统调用需要的参数个数也不同,有的会需要ebx、ecx、edx三个寄存器的值做参数,大多数系统调用完成之后是会返回用户程序继续执行的,_exit系统调用特殊。

x86汇编的两种语法:intel语法和AT&T语法
x86汇编一直存在两种不同的语法,在intel的官方文档中使
用intel语法,Windows也使用intel语法,而UNIX平台的汇编器一
直使用AT&T语法,所以本书使用AT&T语法。 mov %edx,%eax 这条
指令如果用intel语法来写,就是 mov eax,edx ,寄存器名不加 % 号,
并且源操作数和目标操作数的位置互换。本书不详细讨论这两种
语法之间的区别,读者可以参考[AssemblyHOWTO]。
介绍x86汇编的书很多,UNIX平台的书都采用AT&T语法,例
如[GroudUp],其它书一般采用intel语法,例如[x86Assembly]。

二、x86的寄存器

  x86的通用寄存器eaxebxecxedxediesi。这些寄存器在大多数指令中是可以任意使用的。但有些指令限制只能用其中某些寄存器做某种用途,例如除法指令idivl规定被除数在eax寄存器中,edx寄存器必须是0,而除数可以是任何寄存器中。计算结果的商数保存在eax寄存器中(覆盖被除数),余数保存在edx寄存器。

  x86的特殊寄存器ebpespeipeflags。eip是程序计数器。eflags保存计算过程中产生的标志位,包括进位、溢出、零、负数四个标志位,在x86的文档中这几个标志位分别称为CF、OF、ZF、SF。ebp和esp用于维护函数调用的栈帧。

  esp为栈指针,用于指向栈的栈顶(下一个压入栈的活动记录的顶部),而ebp为帧指针,指向当前活动记录的底部。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。

  注意:ebp指向当前位于系统栈最上边一个栈帧的底部,而不是系统栈的底部。严格说来,“栈帧底部”和“栈底”是不同的概念;esp所指的栈帧顶部和系统栈的顶部是同一个位置。

三、第二个汇编程序

求一组数最大值的汇编程序:

.section .data
data_items:
.long 3,67,34,222,45,75,54,34,44,33,22,11,66,0
.section .text
.globl _start
_start:
movl $0, %edi
movl data_items(,%edi,4), %eax
movl %eax, %ebx
start_loop:
cmpl $0, %eax
je loop_exit
incl %edi
movl data_items(, %edi,4), %eax
cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop
loop_exit:
mov $1, %eax
int $0x80

汇编链接执行,然后echo $?会看到输出222。

这个程序在一组数中找到一个最大的数,并把它作为程序的退出状态。这段数在.data段给出:

data_items:
.long 3,67,34,222,45,75,54,34,44,33,22,11,66,0

.long指示声明一组数,每个数32位,相当于C数组。数组开头有个标号data_items,汇编器会把数组的首地址作为data_items符号所代表的地址,data_items类似于C中的数组名。data_items这个标号没有.globl声明是因为它只在这个汇编程序内部使用,链接器不需要知道这个名字的存在。除了.long之外常用的声明:

  • .byte,也是声明一组数,每个数8位
  • .ascii,例: .ascii "Hello World",声明了11个数,取值为相应字符的ASCII码。和C语言不同的是这样声明的字符串末尾是没有'\0'字符的。

data_items数组的最后一个数是0,我们在一个循环中依次比较每个数,碰到0的时候就终止循环。在这个循环中:

  • edi寄存器保存数组中的当前位置,每次比较完一个数就把edi的值加1,指向数组中的下一个数。
  • ebx寄存器保存到目前为止找打的最大值,如果发现有更大的数就更新ebx的值。
  • eax寄存器保存当前要比较的数,每次更新edi之后,就把下一个数读到eax中。
_start:
movl $, %edi

初始化edi,指向数组的第0个元素。

movl data_items(,%edi,), %eax

这条指令把数组的第0个元素传送到eax寄存器中。data_items是数组的首地址,edi的值是数组的下标,4表示数组的每个元素占4字节,那么数组中第edi个元素的地址应该是data_items+edi*4。从这个地址读数据,写成指令就是上面那样。

movl %eax, %ebx

ebx的初始值也是数组的第0个元素。

下面进入一个循环,在循环的开头用标号start_loop表示,循环的末尾之后用标号loop_exit表示。

start_loop:
cmpl $, %eax
je loop_exit

比较eax的值是不是0,如果是0就说明到了数组末尾了,就要跳出循环。cmpl指令将两个操作数相减,但计算结果并不保存,只是根据计算结果改变eflags寄存器中的标志位。如果两个操作数相等,则计算结果为0,eflags中的ZF位置1。je是一个条件跳转指令,它检查eflags中的ZF位,ZF位为1则发生跳转,ZF位为0则不跳转继续执行下一条指令。(条件跳转指令和比较指令是配合使用的)je的e就表示equal

incl %edi
movl data_items(,%edi,), %eax

将edi的值加1,把数组中的下一个数组传送到eax寄存器中。

cmpl %ebx, %eax
jle start_loop

把当前数组元素eax和目前为止找到的最大值ebx做比较,如果前者小于等于后者,则最大值没有变,跳转到循环开头比较下一个数,否则继续执行下一条指令。jle也是一个条件跳转指令,le表示less than or equal

movl %eax, %ebx
jmp start_loop

更新了最大值ebx然后跳转到循环开头继续比较下一个数。jmp是一个无条件跳转指令,什么条件也不判断直接跳转。loop_exit标号后面的指令用_exit系统调用来退出程序。

四、寻址方式

访问内存时在指令中可以用多种方式表示内存地址。内存寻址在指令中可以表示成如下的通用格式:

ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)

它所表示的地址可以这样计算出来:

FINAL ADDRESS = ADDRESS_OR_OFFSET + BASE_OR_OFFSET + MULTIPLIER * INDEX

其中ADDRESS_OR_OFFSET和MULTIPLIER必须是常数,BASE_OR_OFFSET和INDEX必须是寄存器。在有些寻址方式中会省略这4项中的某些项,相当于这些项是0。

  • 直接寻址:只使用ADDRESS_OR_OFFSET寻址,例如movl ADDRESS, %eax把ADDRESS地址处的32位数传送到eax寄存器。
  • 变址寻址:movl data_items(,%edi,4), %eax就属于这种方式,用于访问数组很方便
  • 间接寻址:只使用BASE_OR_OFFSET寻址,例如movl (%eax), %ebx,把eax寄存器的值看作地址,把这个地址处的32位数传送到ebx寄存器。
  • 基址寻址:只使用ADDRESS_OR_OFFSET和BASE_OR_OFFSET寻址,例如movl 4(%eax), %ebx,用于访问结构体成员比较方便,例如一个结构体的基地址保存在eax寄存器中,其中一个成员在结构体内偏移量是4字节,要把这个成员读上来就可以用这条指令。
  • 立即数寻址:就是指令中有一个操作数是立即数,例:movl $3, %eax。
  • 寄存器寻址:就是指令中有一个操作数是寄存器。在汇编程序中寄存器用助记符来表示,在机器指令中则要用几个Bit表示寄存器的编号,这几个Bit与可以看做寄存器的地址,但是和内存地址不在一个地址空间。

关于汇编程序的Hello World可以参看我的另一篇文章:http://www.cnblogs.com/orlion/p/5316519.html

x86汇编程序基础(AT&T语法)的更多相关文章

  1. mySQL的安装和基础使用及语法教程

    mySQL的安装和基础使用及语法指南 一.MySQL的安装.配置及卸载 1.安装 2.配置 3.mySQL5.1的完全卸载 4.MYSQL环境变量的配置 二.MySQL控制台doc窗口的操作命令 1. ...

  2. React实例入门教程(1)基础API,JSX语法--hello world

      前  言 毫无疑问,react是目前最最热门的框架(没有之一),了解并学习使用React,可以说是现在每个前端工程师都需要的. 在前端领域,一个框架为何会如此之火爆,无外乎两个原因:性能优秀,开发 ...

  3. 【原创】React实例入门教程(1)基础API,JSX语法--hello world

    前  言 毫无疑问,react是目前最最热门的框架(没有之一),了解并学习使用React,可以说是现在每个前端工程师都需要的. 在前端领域,一个框架为何会如此之火爆,无外乎两个原因:性能优秀,开发效率 ...

  4. HTML&CSS基础-CSS的语法

    HTML&CSS基础-CSS的语法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.dome.html源代码 <!DOCTYPE html> <html ...

  5. JavaScript基础概念与语法

    学习了一些最基础的JavaScript语法: <!DOCTYPE html> <html lang="en"> <head> <meta ...

  6. postgresql数据库学习-win平台下SQLshell基础操作及语法

    由于在学习https://www.bilibili.com/video/av24590479小马视频时, up主采用的linux虚拟机进行教学, 而本人采用window7进行操作,故在基础操作和语法上 ...

  7. .net 开源模板引擎jntemplate 教程:基础篇之语法

    一.基本概念 上一篇我们简单的介绍了jntemplate并写了一个hello world(如果没有看过的,点击查看),本文将继续介绍jntemplate的模板语法. 我们在讲解语法前,首先要了解一下标 ...

  8. GO语言基础(结构+语法+类型+变量)

    GO语言基础(结构+语法+类型+变量) Go语言结构 Go语言语法 Go语言类型 Go语言变量       Go 语言结构 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 &a ...

  9. 基础SQL语句/语法

    SQL是现在进入互联网工作人们的必须技能之一,下面分享自己觉得很nice的SQL基本语句,从网上找了,觉得很不错,就分享给大家!简要介绍基础语句: 1.说明:创建数据库  Create DATABAS ...

随机推荐

  1. c#去除List中的重复项

    List<string> list = new List<string> {"a", "a", "b", " ...

  2. NOIP2016普及总结

    ---恢复内容开始--- 当时我说如果不出意外有385,结果就这么跪在了第二题,惨啊 本来以为发挥算正常,结果这发挥太不正常了 [T1] 水题啊[趴 注意下细节就好考你会不会写代码. [T2] 这题大 ...

  3. 使用神经网络来识别手写数字【译】(三)- 用Python代码实现

    实现我们分类数字的网络 好,让我们使用随机梯度下降和 MNIST训练数据来写一个程序来学习怎样识别手写数字. 我们用Python (2.7) 来实现.只有 74 行代码!我们需要的第一个东西是 MNI ...

  4. 客户端连接注册Ejabberd新用户

    今天需要使用客户端注册新用户,结果发现注册失败,在管理后台添加新用户成功.编译安装ejabberd就没有管了,经过翻论坛的到解决方法 在ejabberd.yml中. access: trusted_n ...

  5. 设置Flush刷新模式setFlushMode()

    参考 http://blog.csdn.net/superdog007/article/details/38852399 FlushMode的枚举值: FlushMode.ALWAYS:任务一条SQL ...

  6. *HDU 1237 栈

    简单计算器 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  7. 【腾讯Bugly干货分享】Android ImageView 正确使用姿势

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5832602d7196970d65901d76 导语 本文主要介绍了ImageV ...

  8. Java Socket

    什么是Socket Socket的概念很简单,它是网络上运行的两个程序间双向通讯的一端,既可以接收请求,也可以发送请求,利用它可以较为方便地编写网络上数据的传递. 所以简而言之,Socket就是进程通 ...

  9. 借助 Lucene.Net 构建站内搜索引擎(上)

    前言:最近翻开了之前老杨(杨中科)的Lucene.Net站内搜索项目的教学视频,于是作为老杨脑残粉的我又跟着复习了一遍,学习途中做了一些笔记也就成了接下来您看到的这篇博文,仅仅是我的个人笔记,大神请呵 ...

  10. 大白话讲解Promise(三)搞懂jquery中的Promise

    前两篇我们讲了ES6中的Promise以及Promise/A+规范,在Promise的知识体系中,jquery当然是必不可少的一环,所以本篇就来讲讲jquery中的Promise,也就是我们所知道的D ...