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

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

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

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

解决方案——代码

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

%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. 【.Net】c# 中config.exe 引发的一些问题

    public static void CreateConfig(){ //c#可以添加内置的app.config,我们通过ConfigrationManager类可以 //可以很轻松的操作相关节点,操 ...

  2. Lucene笔记二

    lucene 的排序 package cn.itcast.lucene; import java.io.IOException; import org.apache.lucene.document.D ...

  3. 【bzoj1672】[USACO2005 Dec]Cleaning Shifts 清理牛棚 dp/线段树

    题目描述 Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now ...

  4. Python logging(日志)模块

    python日志模块 内容简介 1.日志相关概念 2.logging模块简介 3.logging模块函数使用 4.logging模块日志流处理流程 5.logging模块组件使用 6.logging配 ...

  5. 如何正确实现Page接口分页,用PageImpl 自定义分页

    /** * Constructor of {@code PageImpl}. * * @param content the content of this page, must not be {@li ...

  6. BZOJ4198 & 洛谷2168 & UOJ130:[NOI2015]荷马史诗——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4198 https://www.luogu.org/problemnew/show/P2168 ht ...

  7. 洛谷 P2617 Dynamic Rankings 解题报告

    P2617 Dynamic Rankings 题目描述 给定一个含有\(n\)个数的序列\(a[1],a[2],a[3],\dots,a[n]\),程序必须回答这样的询问:对于给定的\(i,j,k\) ...

  8. SQL_MODE

    一 声明 标红部分为重点了解 原文:https://segmentfault.com/a/1190000005936172 二 SQL_MODE参数值 官方手册专门有一节介绍 https://dev. ...

  9. shell中的颜色显示

    By francis_hao    Sep 30,2017   图片来自参考[1]     其中,"033"是八进制数,其对应的asciima也就是ESC.后面的颜色格式为:[背景 ...

  10. Codeforces Round #532 (Div. 2):F. Ivan and Burgers(贪心+异或基)

    F. Ivan and Burgers 题目链接:https://codeforces.com/contest/1100/problem/F 题意: 给出n个数,然后有多个询问,每次回答询问所给出的区 ...