Rak*_*esh 5 arm instruction-set
为什么是两条单独的指令而不是一条指令?实际上在什么样的情况下我们需要使用CMP和TEQ指令。
我知道这两条指令是如何运作的。
简而言之:两者都有不同的目的,cmp没有subs目的地,而teq没有eors目的地。
cmp非常简单:比较两个
有符号的数字 A 和 B:
gt: A > B
ge: A >= B
eq: A == B
le: A <= B
lt: A < B
无符号:
hi: A > B
hs: A >= B
eq: A == B
ls: A <= B
lo: A < B
让我们假设下面的问题:
int32_t foo(int32_t A)
{
if (((A < 0) && ((A & 1) == 1)) || ((A >= 0) && ((A & 1) == 0)))
{
A += 1;
}
else
{
A -= 1;
}
return A;
}
Run Code Online (Sandbox Code Playgroud)
在人类语言中,如果 A 是(奇数负数)或(偶数正数),则 if 语句为真,并且Linaro GCC 7.4.1 @ O3会产生以下混乱:
foo
0x00000000: CMP r0,#0
0x00000004: AND r3,r0,#1
0x00000008: BLT {pc}+0x14 ; 0x1c
0x0000000C: CMP r3,#0
0x00000010: BEQ {pc}+0x14 ; 0x24
0x00000014: SUB r0,r0,#1
0x00000018: BX lr
0x0000001C: CMP r3,#0
0x00000020: BEQ {pc}-0xc ; 0x14
0x00000024: ADD r0,r0,#1
0x00000028: BX lr
Run Code Online (Sandbox Code Playgroud)
精通比特黑客领域的人会更改 if 语句,如下所示:
int32_t bar(int32_t A)
{
if ((A ^ (A<<31)) >= 0)
{
A += 1;
}
else
{
A -= 1;
}
return A;
}
Run Code Online (Sandbox Code Playgroud)
结果是:
bar
0x0000002C: EORS r3,r0,r0,LSL #31
0x00000030: ADDPL r0,r0,#1
0x00000034: SUBMI r0,r0,#1
0x00000038: BX lr
Run Code Online (Sandbox Code Playgroud)
最后,汇编程序员将替换EORS为teq r0, r0, lsl #31.
它不会使代码更快,但它不需要R3作为暂存寄存器。
请注意,上面的代码只是一个演示案例,它是一个单独的函数,其中有多余的可用寄存器。
然而,在现实生活中,寄存器是迄今为止最稀缺的资源,尤其是在循环内,甚至编译器也会在类似情况下使用该teq指令。
总而言之,在纠错、解密/加密等领域需要xor进行大量操作,处理这些问题的人们只知道欣赏诸如teq以及何时使用它们之类的指令。
永远记住:永远不要相信编译器
| 归档时间: |
|
| 查看次数: |
3768 次 |
| 最近记录: |