arm 数据比较基础知识

时间:2021-11-27 17:12:13

author: hjjdebug
date: 2017-08-24

1. arm 常见的数据比较汇编指令

在utf16向utf8转化时遇到的知识点
数据的大小比较 CMP(相减), TEST(相与)


付实例解析.
int main()
{
int a=5;
int b=6;
if(a==b)
{
printf("a equ b\n");
}
if(a!=b)
{
printf("a not equ b\n");
}
if(a>b)
{
printf("a is big\n");
}
if(a<b)
{
printf("b is big\n");
}
if(a>=b)
{
printf("a greate or equ b\n");
}
if(a<=b)
{
printf("a less or equ b\n");
}
return 0;
}

修改a,b 的值和类型,反汇编其代码,查看其所使用的汇编指令.
x86-32 关键命令:
gcc -march=i386 -m32 -g -o main main.c
objdump -S main > 1.S

arm 编译关键命令
arm-linux-androideabi-gcc -mthumb -g -o main main.c

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

1. c 语言常用的大小比较语句

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

1.相等 if(a==b){}
2.不等 if(a!=b){}
3.大于 if(a>b){}
4.小于 if(a<b){}
5.大于等于 if(a>=b){}
6. 小于等于 if(a<=b){}

2. 对应的无符号数常用比较汇编指令(arm):


cmp a,b
1.相等 bne 跳转到目的地 {相等在这里执行}
2.不等 beq 跳转目的地 {不等在这里执行}
3.大于 bls 跳走 {大于在这里执行}
4.小于 bcs 跳走 {小于在这里执行}
5.大于等于 bcc 跳走 {大于等于在这里执行}
6.小于等于 bhi 跳走 {小于等于在这里执行}

小结:无符号数有点乱, 用carry bit ( set<->clear ),
大于或等于carry位都置位.
还有high <-> low or same 是一对来判别大于,小于等于.

组合标志判别:
HI -> 无符号数大于, Z=0, 并且C=1
LS -> 无符号数小于等于, z=1 或者c=0
CS -> 无符号数大于等于
CC -> 无符号数小于


3. 对应的有符号数常用比较汇编指令(arm):


cmp a,b
1.相等 bne 跳转到目的地 {}

2.不等 be 跳转目的地 {}
3.大于 ble 跳走 {}
4.小于 bge 跳走 {}
5.大于等于 blt 跳走 {}
6.小于等于 bgt 跳走 {}

有符号数用less,greate, equal

组合标志判别:
GT -> 带符号数大于 N=V
LT -> 带符号数小于 N!=V
GE -> 带符号数大于等于 (N=V, Z 可以为0)
LE -> 带符号数小于等于 (N!=V, Z 可以为0)

========================================

4. 对应的无符号数常用比较汇编指令(x86-32):

========================================

cmp a,b
1.相等 jne 跳转到目的地 {}
2.不等 je 跳转目的地 {}
3.大于 jbe 跳走 {}
4.小于 jae 跳走 {}
5.大于等于 jb 跳走 {}
6.小于等于 ja 跳走 {}

========================================

5. 对应的有符号数常用比较汇编指令(x86-32):

========================================

cmp a,b
1.相等 jne 跳转到目的地 {}
2.不等 je 跳转目的地 {}
3.大于 jle 跳走 {}
4.小于 jge 跳走 {}
5.大于等于 jl 跳走 {}
6.小于等于 jg 跳走 {}

可见等于不等于指令一样,
大于,小于指令不同.
无符号数用below, above 指令 有上,下的概念
有符号数用less, great 指令 小于,大于

2. arm 的标志位. N,Z,C,V 标志的意义

对于c语言产生的汇编码, 可以不用关心这些标志, 当然,关心它, 则能从更深的角度来理解比较的依据. cpu 如何由指令来产生这些标志!
从汇编的角度,也可以直接使用这些标志确定流程.

N(负数标志) N=1表示运算的结果为负数;N=0表示运算的结果为正数或零.
标志判别: MI, PL –> N 标志, PL 整数或零.

Z(零标志) Z=1表示运算的结果为零,Z=0表示运算的结果非零。
标志判别: EQ, NE –> Z 标志, 判别两数是否相等.

C(进位标志) 加法运算(包括CMN):当运算结果产生了进位时(无符号数溢出),C=1,否则C=0。
减法运算(包括CMP):当运算结果不产生借位时(无符号数溢出),C=1,否则C=0。
注意, 减法是不产生借位, c=1, 有点跟跟别人不一样啊!! 就适应它吧!.
标志判别: CS, CC, 判别两个无符号数谁大谁小, 大于等于<->小于
两个数相加,最高位有进位时,c 置位. 表示无符号数溢出了,
两个数相减,最高位无借位位时,c 置位, 表示无符号数没有溢出, 总是有点别扭! 不一致!

V(溢出标志) 对于加减法运算指令,V=1表示符号位溢出, 符号发生了改变
arm 的溢出位是针对有符号数的. 当同符号数相加或者异符号数相减会产生溢出.
2个正数相加,当次高位向最高位进位时,数据已经溢出. 此时和变成了负数
2个负数相加,负数是用补码表示的, 当次高位没有向最高位进位时,数据已经溢出.此时和变成了正数
举例: 以256为模. 正数1-127,负数(-1)-(-128), 还有0
则(-1)+(-1)可表示为 0xFF+0xFF = 0xFE 没有溢出
而(-128)+(-1)可表示为 0x80+0xFF = 0x7F 发生了溢出

同理,两个相异符号数的减法也会有这种情况, 这就是V的指示作用!

标志判别: VS, VC –> V 标志.

N=V 表示大于的解释: 假如2个带符号数A, B,
A为正,B为正, 且A>B, 则A-B, N 为0, V为0
A为正,B为负, 显然A>B, 则A-B, 如果不溢出,N 为0, V为0 如果溢出,则v为1,N也为1(变负)
A为负,B为正, 此时A-B, 如果不溢出,N 为1(负数), V为0(符号不溢出) 不满足要求, 溢出也不满足要求.
A为负,B为负, 且A>B, 则A-B, N 为0(正数), V为0(两个负数相减不会溢出)

3. 从汇编比较指令看数据类型是有符号数还是无符号数.

从上面分析可知, 看条件码可以判别是否是有符号数.