汇编条件判断整理(JCC,CMP/TEST的实现)
比较的实现
我们知道CMP是比较两个寄存器内容的指令,但这是如何实现的?
当执行到CMP指令的时候会读取这两个寄存器的内容,并加以减法运算,结果本身不保留,并按照结果设置符号位(属算术运算)。
CMP是一个经常使用的指令,大多用来测试数字的大小。一个常见的例子
MOV EAX, 10
MOV EAX, 10
CMP EAX, EBX ;相减求出结果,为0,将1存入ZF
JE SOME_WHERE ;检查ZF,为1就跳
JNE SOME_WHERE ;检查ZF,为0就跳
当执行到TEST指令的时候会读取这两个寄存器的内容,并加以按位与运算,结果不保留,并按照结果设置符号位(属逻辑运算)。
TEST是一个用来检测内容而不是运算内容的,经常用的一招是测试寄存器是否为0:
TEST EAX, EAX
JZ SOME_WHERE某个参考资料说
TEST EAX,EBX与AND EAX,EBX是一样的,窃以为不同,因为汇编的所有算术指令都是破坏性的,它会把结果存入 EAX,而TEST不会(就像C代码a &= b;)。若要 AND 也不会破坏原值,只能先入栈存值,然后在出栈前转移结果,就像如下所示:MOV EAX, ?? ;赋值
MOV EBX, ??
PUSH EAX ;入栈保存EAX
AND EAX, EBX ;运算
MOV EDX, EAX ;保存结果
POP EAX ;弹出恢复EAX但是你要自己做一个CMP指令是不切实际的,因为你自己还是要判断符号位的值,最终还是用到了TEST, CMP这些指令。
符号位表
这些符号位存在一个叫做PSW(Program Status Word,程序状态字)的16位(4字节)寄存器里面。
| 符号位 | 叙述 | 典型应用 |
| OF | 溢出标志,标明一个溢出的运算。真置1,假置0。 | 这个溢出,非溢出,我想我还没有弄懂 |
| SF | 负号标志,标明结果为负数。真置1,假置0。 |
int i = -100; if(i < 0) goto somewhere; |
| ZF | 零标志,标明结果为0。真置1,假置0。 | 见上cmp例子 |
| CF | 进位标志,标明结果进位了。真置1,假置0。 |
MOV EAX,1 MOV EBX,9 ADD EAX,EBX |
| AF | 辅助进位标志,记录运算时第3位(半个字节)产生的进位。 | <null> |
| PF | 奇偶标志,结果操作数中1的个数为偶置1(我猜是二进制下)。 | <null> |
| DF | 方向标志,在串处理指令中控制信息的方向(非运算) | (null) |
| IF | 中断标志(非运算) | (null) |
| TF | 陷井标志(非运算) | (null) |
其中前几个称为运算条件码(condition code),后三个是逻辑控制标志位,我们在此对它们不感兴趣。
JCC指令表
JCC指条件跳转指令,CC就是指条件码。
| JCC指令 | 中文含义 | 英文原意 | 检查符号位 | 典型C应用 |
| JZ/JE |
若为0则跳转; 若相等则跳转 |
jump if zero; jump if equal |
ZF=1 |
if (i == j); if (i == 0); |
| JNZ/JNE |
若不为0则跳转; 若不相等则跳转 |
jump if not zero; jump if not equal |
ZF=0 |
if (i != j); if (i != 0); |
| JS | 若为负则跳转 | jump if sign | SF=1 | if (i < 0); |
| JNS | 若为正则跳转 | jump if not sign | SF=0 | if (i > 0); |
| JP/JPE | 若1出现次数为偶数则跳转 | jump if Parity (Even) | PF=1 | (null) |
| JNP/JPO | 若1出现次数为奇数则跳转 | jump if not parity (odd) | PF=0 | (null) |
| JO | 若溢出则跳转 | jump if overflow | OF=1 | (null) |
| JNO | 若无溢出则跳转 | jump if not overflow | OF=0 | (null) |
| JC/JB/JNAE |
若进位则跳转; 若低于则跳转; 若不高于等于则跳转 |
jump if carry; jump if below; jump if not above equal |
CF=1 | if (i < j); |
| JNC/JNB/JAE |
若无进位则跳转; 若不低于则跳转; 若高于等于则跳转; |
jump if not carry; jump if not below; jump if above equal |
CF=0 | if (i >= j); |
| JBE/JNA |
若低于等于则跳转; 若不高于则跳转 |
jump if below equal; jump if not above |
ZF=1或CF=1 | if (i <= j); |
| JNBE/JA |
若不低于等于则跳转; 若高于则跳转 |
jump if not below equal jump if abow |
ZF=0或CF=0 | if (i > j); |
| JL/JNGE |
若小于则跳转; 若不大于等于则跳转 |
jump if less jump if not greater equal |
SF != OF | if (si < sj); |
| JNL/JGE |
若不小于则跳转; 若大于等于则跳转; |
jump if not less; jump if greater equal |
SF = OF | if (si >= sj); |
| JLE/JNG |
若小于等于则跳转; 若不大于则跳转 |
jump if less equal; jump if not greater |
ZF != OF 或 ZF=1 | if (si <= sj); |
| JNLE/JG |
若不小于等于则跳转; 若大于则跳转 |
jump if not less equal jump if greater |
SF=0F 且 ZF=0 | if(si>sj) |
这里有好多相等的指令(啊哈,这里有一个有意思的现象,好多看似不沾边的东西实际上是相等的!),我猜是因为编译器编译起来就更方便了,不过做一个表也没什么难的,这个结论不成立啊……
这里有一点要指出,无符号数用低于、高于来比较,而有符号数用大于、小于比较。
汇编条件判断整理(JCC,CMP/TEST的实现)的更多相关文章
- shell 条件判断语句整理
常用系统变量 1) $0 当前程式的名称 2) $n 当前程式的第n个参数,n=1,2,…9 3) $* 当前程式的任何参数(不包括程式本身) 4) ...
- 一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
问题:3行代码 PDF.NET是一个开源的数据开发框架,它的特点是简单.轻量.快速,易上手,而且是一个注释完善的国产开发框架,受到不少朋友的欢迎,也在我们公司的项目中多次使用.但是,PDF.NET比起 ...
- 求1+2+…+n,要求不能使用乘除法、for、while、if、else、s witch、case 等关键字以及条件判断语句(A?B:C)和不用循环/goto/递归输出1~100的10种写法
来源:据说是某一年某个公司的面试题 题目:求1+2+…+n, 要求不能使用乘除法.for.while.if.else.s witch.case 等关键字以及条件判断语句(A?B:C) 分析:这题本来很 ...
- Python第四天 流程控制 if else条件判断 for循环 while循环
Python第四天 流程控制 if else条件判断 for循环 while循环 目录 Pycharm使用技巧(转载) Python第一天 安装 shell 文件 Python第二天 ...
- 标志寄存器PSW和汇编条件转移指令解释
标志寄存器PSW 标志寄存器PSW(程序状态字寄存器PSW) 标志寄存器PSW是一个16为的寄存器.它反映了CPU运算的状态特征并且存放某些控制标志.8086使用了16位中的9位,包括6个状态标志 ...
- [转] Makefile 基础 (6) —— Makefile 使用条件判断
该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...
- Perl if条件判断
Perl 条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 条件判断常用: True #布尔值 not True #布尔值 ! True ...
- C# if中连续几个条件判断
C# if中连续几个条件判断 1.if (条件表达式1 && 条件表达式2) 当条件表达式1为true时 using System; using System.Collections. ...
- js条件判断时隐式类型转换
Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...
随机推荐
- c# 播放器 支持所有格式
原文:c# 播放器 支持所有格式 ---恢复内容开始--- 直接上代码 internal static class LibVlcAPI { internal struct PointerToArray ...
- 使用Python改写的身份证信息查询小程序
花了几天时间过了一遍python基础.真心感觉python让世界充满了爱…先简单的使用一下python好了,拿以前写的<C语言身份证信息查询系统(修改版)>开刀~ 很多东西,不需要考虑C语 ...
- leetcode第36题--Sudoku Solver
题目: Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated b ...
- sql 行转列总结
原文:sql 行转列总结 PIVOT UNPIVOT的用法 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...
- C#:vs2010无法打开vs2012创建的项目
vs低版本打开高版本创建的项目时会提示"选择的文件是解决方案文件,但是用此应用程序的较新版本创建的,无法打开" 解决办法: 写字板打开解决方案sln文件 将其改成你现在用的vs版本 ...
- 如何让Fortran生成不同的随机数
用Fortran生成随机数的方法很简单,就是: call random_seed ()call random_number (rd) 生成随机数组可以这样: do k = 1,10 call rand ...
- 利用Matlab生成一个网格化的三维三轴椭球面(生成直角坐标)
代码很简单,a,b,c分别为椭球的三轴轴长,a=b=c时得到的是三维球面,a=b!=c时得到的是三维椭球面,a!=b且a!=c且b!=c时得到的是三维旋转椭球面 %生成一个笛卡尔坐标系下三轴椭球表面的 ...
- In C# 代码实现
SOLID 设计原则 In C# 代码实现 [S] Single Responsibility Principle (单一职责原则) 认为一个对象应该仅只有一个单一的职责 namespace Si ...
- JS代码放在head和body中的区别分析
最近一直在忙工作,没有时间来写博客了,不过今天做网站的时候碰到一个问题就是JS脚本存放的位置不同其效果不同.起初我没在意这个问题,后来一直解决不了,通过上网与查资料问同事,终于我明白了,原来我碰到了这 ...
- C#串口通信程序详解
C#串口通信程序详解 摘要:创建C#串口通信程序需要注意什么呢?创建C#串口通信程序的步骤是什么?那么本文就向你详细介绍创建C#串口通信程序集体的内容. 在.NET平台下创建C#串口通信程序,.NET ...