arm v8r中汇编指令TXT的详细用法
好的,我们来详细解析 ARMv8-R 架构中的 TST(Test bits)指令。这是一条极其常用的位测试指令,用于检查寄存器中特定的位是 1 还是 0。
📌 核心概念:什么是“测试位”?
TST 指令的核心作用是:对一个寄存器中的值和另一个操作数进行按位“与”(AND)操作,并根据结果设置条件标志位,但不会存储“与”操作的结果本身。
它的名字 "Test" 非常直观:测试某些位。它不会修改任何通用寄存器的值,只通过条件标志位告诉你测试的结果。
📝 指令格式
TST 指令的基本语法格式如下:
TST{<cond>} <Rn>, <operand2>
{<cond>}:可选的条件码后缀。例如EQ(等于)、NE(不等于)等。如果省略,指令将无条件执行。<Rn>:第一个操作数,是要被测试的源寄存器。<operand2>:第二个操作数,通常是一个位掩码(Bitmask)。它可以是一个立即数或一个寄存器(可选地带有移位操作)。这个掩码决定了要测试Rn中的哪些位。
⚙️ 操作与标志位
TST 指令执行的操作是:
status = Rn AND Operand2
它计算 Rn 和 Operand2 的按位与值,并根据这个计算结果更新状态寄存器(CPSR 或 APSR)中的条件标志位,但“与”的结果本身会被丢弃,不保存到任何寄存器。
其结果会影响以下条件标志位:
| 标志位 | 全称 | 含义 | TST 下的设置条件 |
|---|---|---|---|
| N (Negative) | Negative | 表示结果的符号(最高位) | 若“与”操作结果的最高位为 1,则 N 标志被置 1;否则清 0。 |
| Z (Zero) | Zero | 表示结果是否为零 | 若“与”操作结果为 0,则 Z 标志被置 1;否则清 0。这是 TST 最常用的标志。 |
| C (Carry) | Carry | 在 TST 中,此标志位的含义较为特殊 |
如果 Operand2 是一个包含移位操作的寄存器(如 R2, LSL #3),则 C 标志会被设置为移位操作移出的最后一位。否则,C 标志通常保持不变。 |
| V (oVerflow) | Overflow | 溢出标志 | 在 TST 指令中,V 标志不受影响,始终保持不变。 |
核心要点:
TST指令的本质是非破坏性的按位与操作。- Z 标志是
TST的灵魂:- 如果 Z = 1:表示
Rn AND Operand2的结果为 0。这意味着在Operand2掩码中所有为1的位上,Rn中对应的位全都是0。 - 如果 Z = 0:表示
Rn AND Operand2的结果不为 0。这意味着在Operand2掩码中至少有一个为1的位上,Rn中对应的位是1。
- 如果 Z = 1:表示
🖥️ 使用场景与示例
1. 检查特定位是否为 0(最常见)
这是 TST 最经典的用途。用一个只有一位为 1 的掩码,可以检查该位是否是 0。
@ 检查 R0 的第 4 位(bit 4)是否为 0
TST R0, #(1 << 4) @ 掩码为 0x10 (二进制 00010000)
@ 如果 R0 的 bit4 是 0,则 (R0 & 0x10) = 0,Z 标志置 1
@ 如果 R0 的 bit4 是 1,则 (R0 & 0x10) != 0,Z 标志清 0
BNE bit_is_set @ 如果 Z=0 (结果非零),说明位被设置了 (是1),跳转
BEQ bit_is_clear @ 如果 Z=1 (结果为零),说明位被清除了 (是0),跳转
2. 检查特定位是否为 1
通过检查“与”操作的结果是否不等于掩码本身,可以判断位是否为 1(但通常直接检查 Z 标志更简单)。
3. 检查多个位是否同时为 0
使用一个多位掩码,可以一次性检查多个位是否全都为 0。
@ 检查 R1 的低 4 位(bit3-0)是否全部为 0
TST R1, #0xF @ 掩码为 0xF (二进制 00001111)
@ 如果 R1 的低4位全是0,则 (R1 & 0xF) = 0,Z 标志置 1
BEQ lower_nibble_clear @ 如果低4位全为0,跳转
4. 检查是否至少有一个位被设置
使用一个多位掩码,如果 Z=0,表示掩码中至少有一位在 Rn 中是 1。
@ 检查 R2 的 bit7 或 bit5 是否至少有一个是 1
TST R2, #((1 << 7) | (1 << 5)) @ 掩码为 0xA0 (二进制 10100000)
BNE at_least_one_set @ 如果结果非0 (Z=0),说明至少有一位是1,跳转
5. 判断一个数的奇偶性(是奇数还是偶数)
通过测试最低位(bit 0)来实现。
TST R0, #1 @ 测试 bit0
BNE is_odd @ 如果 (R0 & 1) != 0 (Z=0),说明是奇数,跳转
BEQ is_even @ 如果 (R0 & 1) == 0 (Z=1),说明是偶数,跳转
🔍 深入理解:TST vs TEQ vs CMP
为了更清晰地理解 TST 的定位,可以参考它与相似指令的对比:
| 指令 | 执行操作 | 主要用途 | 标志位影响 | 示例 |
|---|---|---|---|---|
TST Rn, Op2 |
Rn AND Op2 |
测试寄存器中特定的位是否为 1 或 是否为 0(通常 Op2 是一个位掩码) |
根据按位与结果设置 N, Z;C 由移位决定;V 不变 | TST R0, #0x20 (测试bit5) |
TEQ Rn, Op2 |
Rn EOR Op2 |
测试两个值是否完全相等(所有位匹配);检查符号位 | 根据按位异或结果设置 N, Z;C 由移位决定;V 不变 | TEQ R0, #0xFF (R0是否等于0xFF?) |
CMP Rn, Op2 |
Rn - Op2 |
比较两个数值的大小(有符号数或无符号数) | 根据减法结果设置 N, Z, C, V | CMP R0, #100 (R0 > 100?) |
关键区别:
TST:关心位模式。“在掩码指定的这些位上,有1吗?”或者“在掩码指定的这些位上,都是0吗?”TEQ:关心完全匹配。“这个寄存器的所有位和另一个操作数完全一样吗?”CMP:关心算术值。“这个寄存器的值比另一个操作数大还是小?”
💎 总结
ARMv8-R 中的 TST 指令是一条基于按位与操作来设置条件标志位的测试指令。
- 它的核心作用是:非破坏性地测试一个寄存器中由位掩码指定的某些位是 1 还是 0。
- 它的主要特点是:不保存运算结果,并且不影响溢出标志 V。它通过 Z 标志来传达测试结果。
- 它的常见用途是:
- 检查单个标志位(如外设状态寄存器中的中断标志、就绪位)。
- 检查一组位是否全部为 0。
- 判断奇偶性。
- 在复杂的位操作算法中作为条件判断的第一步。
TST 是底层编程、设备驱动开发和嵌入式系统中进行状态检查的必备工具。掌握它能让你高效地与硬件寄存器进行交互。
浙公网安备 33010602011771号