关于汇编中IT条件代码的问题

Questions about IT conditional codes in assembly

大多数示例都有如下 IT 命令,

ITTE   NE        ; IT can be omitted
ANDNE  r0,r0,r1  ; 16-bit AND, not ANDS
ADDSNE r2,r2,#1  ; 32-bit ADDS (16-bit ADDS does not set flags in IT block)
MOVEQ  r2,r3     ; 16-bit MOV

ITT    AL        ; emit 2 non-flag setting 16-bit instructions
ADDAL  r0,r0,r1  ; 16-bit ADD, not ADDS
SUBAL  r2,r2,#1  ; 16-bit SUB, not SUB
ADD    r0,r0,r1  ; expands into 32-bit ADD, and is not in IT block

ITT    EQ        
MOVEQ  r0,r1
BEQ    dloop     ; branch at end of IT block is permitted

ITT    EQ
MOVEQ  r0,r1
BKPT   #1        ; BKPT always executes
ADDEQ  r0,r0,#1   

我想查看示例中的最后一个 IT 块。 我真的很困惑发生了什么。对于 MOVEQ,我认为它正在检查 r0 = r1,如果它们相等,则将 r1 移动到 r0。但如果它们相等,那没有意义。究竟是怎么回事?

我写了一个拇指代码来检查哪个数字更大:

cmp r0, r1
ITE HS
movhs r0, r0
movlo r0, r1

这里我需要比较 IT 块之前的寄存器... 但是为什么所有的例子都不包括至少在手前的比较呢?是否有另一种方法可以为我的示例编写不包含比较的 IT 块?这些示例中到底发生了什么?

标志是 IT 块内谓词指令的输入。是的,您确实在 it 之前的某个点放置了 cmpadds 或任何其他标志设置指令。以前不一定

您展示的示例用于记录 IT 的极端情况,而不是 full/complete 使用它实际执行特定操作的示例。

条件分支指令的文档通常也不显示标志设置指令。


根据ARM's docs

With the exception of CMP, CMN, and TST, the 16-bit instructions that normally affect the condition code flags, do not affect them when used inside an IT block.

但其中一个示例确实清楚地表明您可以在 IT 块内更改带有 32 位 adds 的标志,这告诉我们允许使用常规 compare/test 指令。

文档没有明确说明在 IT 块中对标志的更改 会影响块内后面的谓词指令。 @DanLewis 的回答证实了他们这样做。

在 ARM 模式下,不需要 IT 块来谓词执行(每条指令中的 4 位编码一个谓词)因此标志设置指令显然会影响后面的指令。它在 Thumb 模式下以相同的方式工作是有道理的,特别是因为 IT 在某些语法中是可选的。 (一些汇编程序会在为 thumb 模式汇编时以统一语法为您插入它。)

@Darklink9110: yes, you can change flags inside an IT block, the docs are clear on that. > They're not clear on whether that has any effect on the rest of the current block.

我在 ARM Cortex-M4 (Thumb-2) 上测试了以下两个函数以找出答案,事实证明,如果 IT 块内的指令更改标志,则同一 IT 块中的后续指令(1) ADC、SBC、RRX 等确实使用了新的标志值,并且 (2) 可能会根据新的标志值更改其 enabled/disabled 状态。

//      Inside an IT block, do instructions that use the carry flag (e.g., ADC) see
//      changes to the carry flag caused by previous instructions in the same IT block?

Test1:  MOV         R0,1        // R0 = 1
        CMP         R0,R0       // C  = 0, Z = 1 (EQ)
        ITT         EQ
        LSRSEQ      R0,R0,1     // C  = 1, Z = 1 (EQ), R0 = 0
        ADCEQ       R0,R0,0     // R0 = R0 + C
        BX          LR          // **Returns 1 in R0**

//      Do flags that are changed by instruction in an IT block update which
//      subsequent instructions in the same IT block are enabled/disabled?

Test2:  MOV         R0,1        // R0 = 1
        CMP         R0,R0       // Z  = 1 (EQ)
        ITT         EQ
        CMPEQ       R0,0        // Z  = 0 (NE)
        MOVEQ       R0,0        // R0 = 0 ? (Disabled!)
        BX          LR          // **Returns 1 in R0**