引言

上一章我们已经介绍了汇编语言的基础部分,包括数据格式、寄存器以及操作数的标识方式,接下来我们就应该去认识一下汇编语言当中的各个指令了。这些指令大多数都非常简单,但是组合在一起却能模拟出我们程序当中想要的任何效果,确实是十分神奇的一件事。

数据传送指令

数据传送指令的目的是为了将一个数据从一个位置复制到另外一个位置。既然如此,那么数据传送指令就会包含一个源操作数和一个目的操作数,指令会将原操作数的值复制到目的操作数并覆盖。

数据传送指令一共可分为五种,分别是mov、movs、movz、push以及pop,下面LZ依次介绍一下这五个指令的作用。

mov指令

mov指令的作用是将源操作数S中的数据复制到目的操作数D中,mov指令有一个数据格式和两个操作数,因此一般的形式为[movx S D]。其中x为数据格式,S为源操作数,D为目的操作数。

这里举一个简单的例子,比如我们有一条指令为movl %edx %eax。那么它的执行过程就如下图所示。

可以看到,在指令执行之后,%edx寄存器当中的内容会被复制到%eax寄存器。需要一提的是,mov指令可以在后面加上任何数据格式,比如上面这一过程中,数据格式则为四个字节,也就是双字。因此不难推断出,我们还可以使用movb和movw去复制一个字节或者两个字节。

movs指令

movs指令的作用是将源操作数S中的数据做符号扩展后,再复制到目的操作数D中,movs指令有两个数据格式和两个操作数,因此一般的形式为[movsxy S D]。其中x、y为数据格式,S为源操作数,D为目的操作数。其中x、y的组合一共有三种,分别是bw、bl、wl,这三个组合代表的意思分别是单字节到双字节,单字节到双字以及双字节到双字。

这里LZ依然举一个例子,对于指令movswl %dx %eax来讲,它的作用如下图所示。

这里为了可以看出符号位的扩展,因此LZ这里使用了十六进制的整数表示方式。可以看到,movs指令将0x8FFF扩展以后存入%eax寄存器,其中%dx为寄存器%edx的后16位表示。

movz指令

movz指令的作用是将源操作数S做零扩展后,再复制到目的操作数中。它与movs指令十分相似,也有两个数据格式和两个操作数,因此一般的形式为[movzxy S D]。其中x、y为数据格式,S为源操作数,D为目的操作数。其中x、y的组合一共有三种,分别是bw、bl、wl,这三个组合代表的意思分别是单字节到双字节,单字节到双字以及双字节到双字。

这里依然采用相似的示例,我们来看看对于指令movzwl %dx %eax来讲,它的作用与上面的movs有何不同。

可以看出,movz与movs指令是十分相似的,只是这里扩展后,目标寄存器%eax的前16位为0而不再是1。

push指令

push指令与上面的mov族指令有着不同,它的目的操作数被固定为栈顶,因此它的指令当中没有目的操作数。另外有一点需要注意的是,它在进行复制操作之前,需要移动栈顶指针(-4)。push指令的一般形式为[pushl S],其中l代表数据格式为双字,S为源操作数,目的操作数默认为栈顶。

这里LZ举一个简单的例子,比如pushl %edx这条命令,它的任务是将%edx寄存器的值复制到栈顶。我们首先来看一下命令执行前,寄存器以及存储器的状态。

可以看到,寄存器%ebp和%esp分别指向帧指针和栈指针,而%esp实际上就是指向的栈顶。由于现在栈顶位于-16的位置,因此若要将%edx压入栈,则先需要将栈顶移动到-20的位置,然后再进行复制,移动后的状态如下图所示。

可以看到,这里栈指针的位置已经发生了变化,向下移动了四位,并且将%edx寄存器的值放入新的栈顶,因此pushl %edx指令就相当于下面两条指令。

subl $4,%esp

movl %edx,(%esp)

这里可以看出来,其实pushl指令做了一个隐藏操作,就是移动栈指针(-4),这一点希望各位猿友们注意。

pop指令

pop指令与push指令是做的相反的操作,一个是入栈一个是出栈。对于pop指令来讲,它的源操作数被固定为栈顶,相反,它会先进行复制操作,然后再移动栈指针。pop指令的一般形式为[popl D],其中l代表数据格式为双字,D为目的操作数,源操作数默认为栈顶。

接下来我们举一个例子,与上面的例子类似,我们考虑popl %edx这条指令的效果,它会将栈顶的值弹出到寄存器%edx。首先来看执行之前,寄存器以及存储器的状态。

接下来执行pop指令时,会先将栈顶的值复制到%edx,然后再将栈指针移动(+4)。我们来看一下它执行后的状态。

可以看到,之前栈顶的内容已经被弹出到%edx寄存器,并且当前栈顶已经移动到了-16的位置,也就是进行了+4操作。因此popl %edx指令就相当于下面两条指令。

movl (%esp),%edx

addl $4,%esp

这里可以看出来,其实popl指令也同样做了一个隐藏操作,就是移动栈指针(+4)。

数据复制示例

上面我们已经了解了几乎所有的数据复制指令,接下来我们写一小段程序,来看下这些数据复制指令,如何完成我们的程序操作。

simple(int *xp,inty){int t = *xp;*xp=y;returnt;

}

上面是一个简单的C程序sum.c,它其中包含了一些赋值操作,我们来看看它的汇编代码。使用GCC -O1 -S sum.c来获取我们的汇编代码,并使用cat sum.s来查看一下。

.file "sum.c".text

.globl simple

.type simple, @function

simple:

pushl%ebp

movl%esp, %ebp

//以上为栈的建立部分

movl8(%ebp), %edx

movl (%edx), %eax

movl12(%ebp), %ecx

movl%ecx, (%edx)

//以下为栈的完成部分

popl%ebp

ret

.size simple, .-simple

.ident"GCC: (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3".section .note.GNU-stack,"",@progbits

分析这段汇编代码的时候,我们应该分为三个部分来看待,首先是栈的建立、然后是使用、最后是完成部分。可以看到,里面几乎全是数据复制指令,我们先来看看栈的建立部分。

其实对于一开始pushl和movl指令来讲,它主要做了两件事。第一个是将原来的帧指针备份到栈顶,然后再将帧指针和栈指针统一指向这个新的栈顶,也就是完成了一个新栈的建立。它在完成后,栈的状态如下所示。

可以看到,寄存器%ebp和寄存器%esp都指向当前帧指针的位置,其中变量xp位于+8的位置,而y位于+12的位置。由于xp是一个指针变量,因此它会指向一个内存中的区域,其中的值为*xp。

了解完寄存器和存储器的状态,此时栈已经建立完毕,接下来我们看紧接着的一句汇编代码的作用。

movl 8(%ebp), %edx

这一句将内存地址为%ebp+8的值复制到%edx,很明显,从上面的图中可以看出,%ebp+8这个位置存储着xp变量。这一句指令做了一个简单的操作,就是将xp提取到%edx寄存器,如下所示。

此时已经将%edx的值改为了变量xp,看接下来的一句操作。

movl (%edx), %eax

这一句将内存地址为%edx的值赋给寄存器%eax,并准备返回值。此时%edx寄存器的值已经改为了xp变量,因此(%edx)其实就是*xp,而%eax寄存器一般会作为函数的返回值,因此它其实替代了临时变量t。执行后的状态如下所示。

此时其实已经完成了程序中的int t = *xp以及为return t准备好了返回值,接下来的一句汇编代码作用也非常简单,如下。

movl 12(%ebp), %ecx

它的作用是将地址为%ebp+12的值复制到寄存器%ecx,从图中可以看出,%ebp+12就是存储的变量y。因此它的作用就是将y复制到寄存器%ecx,如下所示。

上面这一步挺简单,我们来看最后一步操作,如下。

movl %ecx, (%edx)

它的作用是将%ecx寄存器的值复制到内存中%edx的位置。此时%ecx的值为y,而%edx中为xp,因此目的操作数则为xp指向的位置,也就是*xp。这一句话执行的就是程序代码当中,*xp=y这个操作,它执行后的状态如下所示。

可以看到,在执行了*xp=y以后,xp指针所指向的位置,其值已经变为了y。此时程序其实已经基本运行完毕,剩下的工作也就是栈的完成操作了,也就是popl指令。在栈完成之后,也就是pop指令执行之后,当前帧会恢复到调用者的帧上面去,如下所示。

此时当前帧已经恢复到了调用者的帧,最后ret指令会改变程序计数器(PC)的值,然后跳出子函数,继续执行调用者当中的代码。到此,我们的数据复制示例就结束了,尽管这个例子并不难,但是麻雀虽小五脏俱全,如果理解了这个过程,相信就算是再复杂一些的汇编指令,也只是分析的时间长一点罢了。

文章小结

本章内容比较长,LZ为了便于理解,插入了不少图,希望对各位有帮助,不过这些图是真不好画,浪费了LZ不少时间。本次主要介绍了一些数据复制指令,都是复制来复制去的,下一章我们将讨论一下有关计算的指令,那里会有一些加减乘除、移位、取地址等操作。

movs 数据传送指令_深入理解计算机系统(3.3)---数据传送(或者说复制)指令详解...相关推荐

  1. 深入理解计算机系统 -资料整理 高清中文版_在所不辞的博客-CSDN博客_深入理解计算机系统第四版pdf

    深入理解计算机系统 -资料整理 高清中文版_在所不辞的博客-CSDN博客_深入理解计算机系统第四版pdf

  2. Linux I/O操作fsync后数据就安全了么(fsync、fwrite、fflush、mmap、write barriers详解)

    系列文章 Linux I/O操作fsync后数据就安全了么(fsync.fwrite.fflush.mmap.write barriers详解) Linux I/O系列之直接内存(Direct IO) ...

  3. 深入理解计算机系统第四版_深入理解计算机系统之存储器层次结构

    我的计算机模型是这样的: CPU执行指令,内存犹如一个巨大的字节数组,存储着指令和数据,硬盘保存着各种程序与程序用到的数据.I/O完成输入输出的功能.在本文中我们抛开I/O,谈一谈关于CPU,内存,硬 ...

  4. 深入理解计算机系统(3.5)---特殊的算术操作指令详解

    引言 上一章我们讨论了常见的算术与逻辑运算指令,其中比较有特点的是leal指令,本章我们再来看几个比较特殊的操作指令,这些指令可以让只有32位的寄存器存储64位的数据,是不是十分霸气侧漏呢. 初识 我 ...

  5. 一维数据高斯滤波器_透彻理解高斯混合模型

    高斯混合模型GMM是一个非常基础并且应用很广的模型.对于它的透彻理解非常重要. 本文从高斯分布开始逐步透彻讲解高斯混合模型 高斯分布 高斯分布有两个参数: μ = mean(数据的中心) σ2 =va ...

  6. 大数据相关从业_如何在组织中以数据从业者的身份闪耀

    大数据相关从业 Build bridges, keep the maths under your hat and focus on serving. 架起桥梁,将数学放在脑海中,并专注于服务. 通过协 ...

  7. 数据数据泄露泄露_通过超参数调整进行数据泄漏

    数据数据泄露泄露 介绍 (Introduction) Data Leakage is when the model somehow knows the patterns in the test dat ...

  8. 软件开发向大数据开发过渡_如果您是过渡到数据科学的开发人员,那么这里是您的最佳资源...

    软件开发向大数据开发过渡 by Cecelia Shao 邵Ce It seems like everyone wants to be a data scientist these days - fr ...

  9. python 3d大数据可视化软件_最受欢迎的大数据可视化软件

    最受欢迎的大数据可视化软件 发布时间:2020-05-26 想像阅读书本一样阅读数据流?这只有在电影中才有可能发生. 在现实世界中,企业必须使用数据可视化工具来读取原始数据的趋势和模式. 大数据可视化 ...

  10. 数据科学与大数据排名思考题_排名前5位的数据科学课程

    数据科学与大数据排名思考题 目录 (Table of Contents) Introduction介绍 Udemy乌迪米 Machine Learning A-Z™: Hands-On Python ...

最新文章

  1. 使用t-SNE算法对数据进行降维并可视化实战,与KernalPCA、LLE对比降维可视化的效果
  2. opencv_4.5.0/OpenCvSharp_已知目标物边界求重心
  3. 我说分布式事务之消息最终一致性事务(一):原理及实现
  4. 转载 SharedPreference.Editor的apply和commit方法异同
  5. 封装自己的控件库:iPhone静态库的应用
  6. Jmeter分布式压测方案
  7. 快速融入新团队的一点个人体会
  8. java 彩铃开发,motorola铃声算法,是java的!_移动短信技术
  9. VSCode调试Python时终端输出中文乱码解决方法1
  10. 问题3:点击应用icon,会卡几秒后才进入到启动界面
  11. js window.open 参数设置
  12. django mysql socket_django mysql 读写分离
  13. 【怎样防止黑客入侵电脑 九个设置让电脑远离黑客】
  14. OSPF基础知识及配置命令
  15. 条件语句的if语句的5种替代方法
  16. iPS细胞治疗糖尿病的研究
  17. 单片机加减法C语言,单片机的加减法原理
  18. core dumped 错误
  19. docker常用命令及镜像的制作与上传
  20. Excel股票分析工具_每日连板清单

热门文章

  1. 【微信小程序】问卷调查/答题类小程序实现
  2. 感觉现在的技术圈越来越像娱乐圈了
  3. 北大美女辞去公司副总职务创业养狗
  4. vue3+vite2警告提示The above dynamic import cannot be analyzed by vite问题,vite中import动态引入
  5. mac_excel_条件格式
  6. 若干个数据首尾相连,构成一个圆环,找到连续的4个数之和最大的一段。 C++
  7. linux怎么做冗余备份,linux下使用raid实现冗余备份
  8. SylixOS -- 双网卡冗余备份设计方案
  9. 我的世界java版1.7.10打不开怎么办_我的世界中国版打不开怎么办 怎么解决
  10. YTU oj 3272: 公民身份号码