我们在上一讲中,简单了解了汇编程序大概的样子。接下来我们来了解一下,汇编程序的大小比较操作。所以我们以编写寻找一堆数中的最大值作为学习的载体。

在编写程序之前,先要分析我们的目的,在得出解决方案。

目的:在一堆数中找到最大的数

思路:要实现这个目的,首先,我们一定要对数据进行索引,每一次比较,两个数应该分别占用一个寄存器,得到最大值,所以,我们有一个寄存器一定是存放最大值的。一开始没有最大值,我们不妨设第一个数为最大值,后面一次索引大小比较。得出最大值。索引中还会用到循环结构。

解决方案——代码

在代码之前,先说一下用到的寄存器

%eax – 用来存储当前数据

%ebx – 用来存储最大值

%edi – 存储索引


.section .data data_items:
.long 3, 14, 15, 9, 26, 53, 58, 97, 93, 2, 38, 4, 36, 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:
movl $1, %eax
int $0x80
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

把上面的代码保存为maximum.s,在编译链接,运行。正常情况下最大应该是97。

现在来具体解释代码:

.section .data 为数据段,前面一节我们提到过。
  • 1
data_items
.long 3, 14, 15, 9, 26, 53, 58, 97, 93, 2, 38, 4, 36, 0
  • 1
  • 2

这是数据段里面的内容,data_items 是标签,代表一个地址。在这个位置后面是一堆数字,这些数字的类型是long(长整形,4字节)。而data_items标签代表的地址就是这段数字的开头,在这个例子中,data_items对应的地址下的内容为long类型的数字3。

这个数据项的末尾的0是人为添加,在这里来作为是否到达末尾的判断依据。

movl $0, %edi
movl data_items( , %edi, 4), %eax
movl %eax, %ebx
  • 1
  • 2
  • 3

这里是为循环做好准备,我们要把索引寄存器%edi的值变为0,应为我们要从数据的第一个数字开始获取数据。

movl data_items( , %edi, 4), %eax 这句是把数据的第一个数据载入到%eax里面。
这里的源操作数是data_items( , %edi, 4),目的操作数是%eax,而源操作数比较复杂,这里涉及到内存里的寻址方式。这一点也是汇编中十分重要的内容。我们下一讲具体来讲解。这里想讲最基本的。在内存中地址引用的通用格式是下面这样:

地址或偏移(%基址寄存器,%索引寄存器,比例因子)

实际地址 = 地址或偏移 + %基址寄存器 + 比例因子 * %索引寄存器

这里用到的是索引寻址方式,是利用地址或偏移、%索引寄存器、比例因子来实现。所以出现了上面代码的表现形式。

在这个例子中data_items为起始地址,后面的各项一一对应,这里的比例因子是4是因为long类型为4字节。

movl %eax, %ebx 把第一个数载入到%ebx中作为最大值。

后面我进入了循环,我们用start_loop来标记循环的入口(位置)。

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

一个循环第一考虑的问题就是,循环结束的条件,不然写出死循环就麻烦了。cmpl —— compare long,比较long类型的大小,结果会记录在%eflags(状态寄存器)中je = jump equal 如果值相等,就跳转。

cmpl $0, %eax
je loop_exit
  • 1
  • 2

表示%eax的值为0就跳转到loop_exit的位置,执行这个位置后面的操作。如果不相等就不跳转,而是继续执行后面紧更的操作。

incl %edi
movl data_items( , %edi, 4 ), %eax
  • 1
  • 2

incl —— increase long,所以 incl %edi 是让%edi的值加1,类似于C语言的 i++ 的效果

所以这两句很在一起的效果就是索引数据,要检测的数着存放在%eax中。

cmpl %ebx, %eax
jle start_loop
movl %eax, %ebx
jmp start_loop
  • 1
  • 2
  • 3
  • 4

jle —— jump less equal如果小于等于,跳转

jmp —— 无条件跳转

所以这里就是,如果%eax里的大值比%ebx中的目前最大值小或相等(注意:比较的方式,到底是那个比那个小),这跳转到start_loop位置,执行这个位置后面的代码,也就是跳过后面操作,回到循环的开头。如果不成立,执行下面步骤,就是把%eax里面的值载入到%ebx作为新的最大值。跳会循环开始处。

movl $1, %eax
int $0x80
  • 1
  • 2

对于这个程序,这么解释,实在是太累了,最为教程的前几期,会讲的详细,每一步都讲,到后面基本之讲重点。

最后,最好在回顾一遍,在写一遍,你可以对其进行改进,这一次写,可不是对着代码敲下来,而是自己写。

附加内容:

数据类型

  • .byte —— 字节类型,只占用一个字节
  • .int —— 整型,占用2个字节
  • .long —— 长整型,占用4个字节
  • .ascii —— ascii码类型字符,一个字符占1个字节

大小判断

  • je = jump equal 如果值相等,就跳转。
  • jg = jump greater 如果第二个值大于第一个值,跳转
  • jge = jump greater equal 如果第二个值大于等于第一个值,跳转
  • jl = jump less equal如果第二个值小于第一个值,跳转
  • jle = jump less equal如果第二个值小于等于第一个值,跳转
  • jmp  无条件跳转

注意:这里的等于只是方便大家理解命令便于理解记忆。

Linux汇编教程03:大小比较操作的更多相关文章

  1. Linux汇编教程01: 基本知识

    在我们开始学习Linux汇编之前,需要简单的了解一下计算机的体系结构.我们不需要特别深入的了解,理解了一些基本概念对与我们理解程序会很有帮助.现在计算机的结构体系都是采用冯诺依曼体系结构的基础上发展过 ...

  2. Linux汇编教程02:编写第一个汇编程序

    学习一门语言,最好的方式就是在运用中学习,那么在这一章节中,我们开始编写我们的第一个汇编程序.当然作为第一个程序,其实十分的简单,但可以给大家一个基本的轮廓,了解汇编大概是这样的. 我们这个程序实际上 ...

  3. Linux汇编教程04:寻址方式

    这一节,我们主要来讨论寻址方式,这一点十分重要. 我们上一节有稍微提了一下,内存地址引用的通用格式: 地址或偏移(%基址寄存器, %索引寄存器, 比例因子 ) 结果地址 = 地址或偏移 + %基址寄存 ...

  4. 嵌入式Linux开发教程:Linux常见命令(上篇)

    摘要:这是对周立功编著的<嵌入式Linux开发教程>的第7期连载.本期刊载内容有关LinuxLinux常见命令中的导航命令.目录命令和文件命令.下一期将连载网络操作命令.安装卸载文件系统等 ...

  5. Linux makefile 教程 非常详细,且易懂(转)

    转自:http://blog.chinaunix.net/uid-27717694-id-3696246.html 原文地址:Linux makefile 教程 非常详细,且易懂 作者:Deem_pa ...

  6. 很详细、很移动的Linux makefile教程:介绍,总述,书写规则,书写命令,使用变量,使用条件推断,使用函数,Make 的运行,隐含规则 使用make更新函数库文件 后序

    很详细.很移动的Linux makefile 教程 内容如下: Makefile 介绍 Makefile 总述 书写规则 书写命令 使用变量 使用条件推断 使用函数 make 的运行 隐含规则 使用m ...

  7. [译]Vulkan教程(03)开发环境

    [译]Vulkan教程(03)开发环境 这是我翻译(https://vulkan-tutorial.com)上的Vulkan教程的第3篇. In this chapter we'll set up y ...

  8. Linux培训教程 linux磁盘分区详解

    在学习 Linux 的过程中,安装 Linux 是每一个初学者的第一个门槛.在这个过程中间,最大的困惑莫过于给硬盘进行分区.虽然,现在各种发行版本的 Linux 已经提供了友好的图形交互界面,但是很多 ...

  9. 调整Linux磁盘分区的大小的方法

      昨天数据入库时,一直报错,说磁盘满了,,df -h    一看,发现/目录下只有50G空间,已使用49G:我的程序和dbss都安装在/目录下,ftp到的数据放在/data下的一个子目录下,分解完的 ...

随机推荐

  1. BZOJ 1787 紧急集合(LCA)

    转换成抽象模型,就是要求一棵树(N个点,有N-1条边表示这个图是棵树)中某一点满足给定三点a,b,c到某一点的距离和最小.那么我们想到最近公共祖先的定义,推出只有集合点在LCA(a,b).LCA(a, ...

  2. US Open 2016 Contest

    比较弱,只写了金组和银组,铂金组的第一题. [262144] http://www.usaco.org/index.php?page=viewproblem2&cpid=648 给一个序列,相 ...

  3. BZOJ3523 [Poi2014]Bricks 【贪心】

    题目链接 BZOJ3523 题解 简单的贪心题 优先与上一个不一样且数量最多的,如果有多个相同,则优先选择非结尾颜色 比较显然,但不知怎么证 #include<algorithm> #in ...

  4. 项目管理---git----快速使用git笔记(一)------git的简单介绍

    最近svn代码管理服务器崩溃了,切换到git来运作. 经过几天的使用,感觉很不错. 尤其是代码合并到正式版本之前 可以对代码进行 code review. 这样能很好的保证团队的代码质量和一些重复代码 ...

  5. jQuery获取元素对象本身的html

    Jquery获取html标签,包含该标签本身 2018年04月01日 20:16:10 清--水 阅读数:829   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.c ...

  6. 背景建模技术(六):帧处理(FrameProcessor)模块

    前面几篇文章简单介绍了BgsLibrary的入口函数.视频分析和视频捕获模块,本文将简单介绍帧处理模块,即对每一帧进行处理的函数,也就是真正调用背景建模算法的接口处. 下面贴出源码供大家分析: #in ...

  7. HDU 5538 (水不水?)

    House Building Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) ...

  8. SCU 4527 NightMare2 最短路+二分 好题

    可怜的又做噩梦了..但是这次跟上次不大一样,虽然他又被困在迷宫里,又被装上了一个定时炸弹,但是值得高兴的是,他发现他身边有数不清的财宝,所以他如果能带着这些财宝并活着逃出去的话,他就发财啦.不过,这次 ...

  9. Mybatis批量更新详解

    转:http://www.cnblogs.com/winkey4986/p/3915151.html Mybatis批量更新 批量操作就不进行赘述了.减少服务器与数据库之间的交互.网上有很多关于批量插 ...

  10. UVA11426

    链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=26&page ...