Ubuntu x86-64汇编(5) 控制指令
控制指令 Control Instructions
汇编的控制指令主要包含标签, 无条件跳转和有条件跳转几种
标签 Label
标签用于标记跳转的目的, 必须以字母开头, 后面跟着字母, 数字和下划线, 最后以冒号:结束
yasm里的标签是区分大小写的
无条件跳转 Unconditional Control Instructions
格式
jmp <label>
jmp startLoop
jmp ifDone
jmp last
条件跳转 Conditional Control Instructions
条件跳转一般发生在一个比较指令之后, 比较的结果决定跳转是否执行. 比较指令的结果会存储在rFlag寄存器. 条件跳转要紧接着比较指令进行, 以免结果被其他指令修改.
比较指令的格式
cmp <op1>, <op2>
<op1> 和 <op2> 必须是同一尺寸且不能修改. 不能同时为内存. <op1>不能为立即数. 跳转指令je和jne对无符号数和有符号数同样适用. 但是其他的跳转指令会有区别, 适用于有符号数的有 jl, jle, jg, jge; 适用于无符号数的有 jb, jbe, ja, jae. 列表如下
je <label> ; if <op1> == <op2>
jne <label> ; if <op1> != <op2>
jl <label> ; signed, if <op1> < <op2>
jle <label> ; signed, if <op1> <= <op2>
jg <label> ; signed, if <op1> > <op2>
jge <label> ; signed; if <op1> >= <op2>
jb <label> ; unsigned, if <op1> < <op2>
jbe <label> ; unsigned, if <op1> <= <op2>
ja <label> ; unsigned, if <op1> > <op2>
jae <label> ; unsigned, if <op1> >= <op2>
举例对于下面的判断语句
if (currNum > myMax)
myMax = currNum;
;先定义变量
currNum dq 0
myMax dq 0
; 代码为
mov rax, qword [currNum]
cmp rax, qword [myMax] ;if currNum <= myMax
jle notNewMax ; skip set new max
mov qword [myMax], rax
notNewMax:
另一个例子
if (x != 0) {
ans = x / y;
errFlg = FALSE;
} else {
ans = 0;
errFlg = TRUE;
}
代码
TRUE equ 1
FALSE equ 0
x dd 0
y dd 0
ans dd 0
errFlg db FALSE
;
;
cmp dword [x], 0 ; if statement
je doElse
mov eax, dword [x]
cdq
idiv dword [y]
mov dword [ans], eax
mov byte [errFlg], FALSE
jmp skpElse
doElse:
mov dword [ans], 0
mov byte [errFlg], TRUE
skpElse:
这个例子中因为是带符号数, 所以使用了idiv和cdq.
超出跳转范围 Jump Out Of Range
一般来讲, 条件跳转的目标标签要在128byte以内, 如果超出的话就会出现jump out-of-range错误. 但是无条件跳转是没有这个限制的. 可以用以下的方法解决这个问题
cmp rcx, 0
je endOfLoop
jmp startOfLoop
endOfLoop:
用je + jmp 代替 jne, 就避免了条件跳转的限制
枚举 Iteration
这个控制指令用于枚举或循环. 一个基本的循环由一个计数器和一个顶上或底下的判断和跳转组成. 例如
maxN dq 30
sum dq 0
; 下面的代码用于计算从1到maxN的奇数之和.
mov rcx, qword [maxN] ; loop counter
mov rax, 1 ; odd integer counter
sumLoop:
add qword [sum], rax ; sum current odd integer
add rax, 2 ; set next odd integer
dec rcx ; decrement loop counter
cmp rcx, 0
jne sumLoop
在这个例子中, rcx 用于循环的计数, rax用于存储当前循环的奇数, 用1初始化并每次加2.
另外我们也可以用loop指令来实现, 其格式如下, 执行时会递减rcx寄存器的值, 与0比较, 当不等于0时跳转(到开始处再次循环)
loop <label>
之前的代码可以用loop改写为:
mov rcx, qword [maxN] ; loop counter
mov rax, 1 ; odd integer counter
sumLoop:
add qword [sum], rax ; sum current odd integer
add rax, 2 ; set next odd integer
loop sumLoop
因为循环中会改写并检查rcx寄存器, 如果未初始化rcx寄存器, 将导致未知的循环次数. loop指令在编程中很有用, 但是受限于rcx寄存器. 如果需要多层的loop, 需要在循环内外进行rcx当前值的保存和恢复.
代码例子 平方数求和 Sum of Squares
; Simple example program to compute the
; sum of squares from 1 to N.
; **********************************************
; Data declarations
section .data
; ----
; Define constants
SUCCESS equ 0 ; Successful operation
SYS_exit equ 60 ; call code for terminate ; Define Data.
n dd 10
sumOfSquares dq 0 ; *******************************************************
section .text
global _start
_start:
; ----
; Compute sum of squares from 1 to N.
; Approach:
; for (i=1; i<N; i++)
; sumOfSqaures += i^2;
mov rbx, 1 ; i
mov ecx, dword [n] sumLoop:
mov rax, rbx ; get i
mul rax ; i^2
add qword [sumOfSquares], rax
inc rbx
loop sumLoop ; ----
; Done, terminate program.
last:
mov rax, SYS_exit ; call code for exit
mov rdi, SUCCESS ; exit with success
syscall
.
Ubuntu x86-64汇编(5) 控制指令的更多相关文章
- Ubuntu x86 64 settup nginx rtmp server
常常搭建nginxserver,可是好像每次的情况都不同,这次具体记录这个过程: 平台:unbutu 10.04 内核:2.6.32-33-generic 1, 编译环境搭建. sudo apt-ge ...
- < IOS > X-code 5.1 x86 - 64 编译问题
关于xcode 5.1 x86 - 64 编译问题 坐等了N久,终于IOS 7.1 发布了,作为一个果粉,忍不住第一时间升级了.结果用设备测试的时候,出问题了,一直检测不到设备,哈哈,纠结了半 ...
- Ubuntu Linux14 64位下在Android studio下用gradle编译Andrid项目时发生libz.so.1共享库找不到的解决方法。
---恢复内容开始--- 我在Ubuntu14 64为下安装了AS,但在用Gradle编译项目时总是报找不到 libz.so.1的错误. error while loading shared libr ...
- 一段简单c程序的汇编语言学习(ubuntu+x86)
c程序代码: #include <stdio.h> int main(void) { int i=0, j=0; for(i=0; i<8; i++) j=j+1; return 0 ...
- ubuntu 32/64 bit
https://askubuntu.com/questions/454253/how-to-run-32-bit-app-in-ubuntu-64-bit how to run 32-bit app ...
- Ubuntu上64位adv无法创建问题
Ubuntu上安装android开发环境,前面都成功了,但到了最后创建adv的时候却总是失败. 出现了这个问题.最后,上网找了这个教程http://blog.sina.com.cn/s/blog_66 ...
- centos(x86 64位系统)使用boost
1. 安装gcc,g++,make等开发环境 yum groupinstall "Development Tools" 2. 安装boost yum install boost b ...
- ubuntu 12 64 桌面版Oracle11g 安装
1.Creating the Oracle Inventory Group sudo groupadd oinstall sudo groupadd dba sudo groupadd oper su ...
- Openfiler能把标准x86/64架构的系统变成一个强大的NAS、SAN存储和IP存储网关
http://www.linuxprob.com/vmware-openfiler.html
随机推荐
- ASP.NET Core 中间件 中间件(Middleware)和过滤器(Filter)的区别
https://www.cnblogs.com/savorboard/p/5586229.html 前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际使用的, ...
- c#中的 数组
数组即是一组相同类型组合在一起,使用一个通用的名称,通过分配的下标访问的数据集合中的元素. 数组是具有相同类型的一组数据.当访问数组中的数据时,可以通过下标来指明.c#中数组元素可以为任何数据类型,数 ...
- windows核心编程-互斥器(Mutexes)
线程同步的方式主要有:临界区.互斥区.事件.信号量四种方式. 前边讲过了临界区线程同步-----windows核心编程-关键段(临界区)线程同步,这章我来介绍一下互斥器(Mutexes)在线程同步中的 ...
- C/C++二叉树搜索树操作集
啥是二叉查找树 在数据结构中,有一个奇葩的东西,说它奇葩,那是因为它重要,这就是树.而在树中,二叉树又是当中的贵族.二叉树的一个重要应用是它们在查找中的应用,于是就有了二叉查找树. 使二叉树成为一颗二 ...
- 整合spring cloud云架构 - SSO单点登录之OAuth2.0登录认证(1)
之前写了很多关于spring cloud的文章,今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAuth2.0的一些基础知识点,帮助大家回顾一下知识点: 一.oauth中的角 ...
- 不用IDE写C#的Hello World
用Visual Studio等IDE写C#的Hello World非常简单,但脱离了IDE你能不能打印出Hello World呢?这不是说工作时脱离IDE,而是学习一下CLR的执行模型. Hello ...
- [转]shell脚本每行的执行顺序是怎样
原文:https://blog.csdn.net/weixin_42609121/article/details/83028000 ---------------------------------- ...
- XenServer修改DNS
XenServer没法直接修改DNS,感觉好奇怪啊 修改方法: 1.进入命令行: 2.执行命令: # xe pif-list 列出网卡的UUID. 3.执行命令: # xe p ...
- 从头来之【MAC下代码管理工具】
本人使用的是一款免费的GIT管理工具SOURCETREE.在appstore下载完后安装. 先选中改变的文件拉倒上面,[COMMIT]---->[push] 如有疑问请留言
- 【nodejs】FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
当使用大批量(>100)的SQL进行MySql数据库插值任务时,会发生以下错误: 总计将有371579条数据将被插入数据库 开始插入DB <--- Last few GCs ---> ...