【问题标题】:convert c to assembly with predicated instruction [closed]使用谓词指令将c转换为程序集[关闭]
【发布时间】:2016-05-14 05:34:10
【问题描述】:

我想使用谓词指令将此代码转换为程序集

If (A>B){

    C=A;
    D=B;
    E=0

}

else{

    C=B;
} 

是正确的还是我该如何使用跳转?

cmp R1,R2; considering B is assigned to R2 and A assigned to R1
movlf R3,R1;R3 assign to C
mov R4,R2;R4 assign to D
mov R5,0; R5 assign to E
movlt R3,R2

【问题讨论】:

  • 你问的是什么汇编语言?

标签: c assembly arm predicates


【解决方案1】:

警告:新手回答。可能会让有经验的用户感到厌烦。


我不确定您是否误用了术语,或者您是否真的想使用predicated instructions1

在后一种情况下,使用ARM v6 predication 作为研究案例(并继承您关于寄存器使用的前提),程序集很简单

;r1 = A    r2 = B    r3 = C    r4 = D    r5 = E
;
;A, B unsigned            | ;A, B signed
                          |
cmp r1, r2                | cmp r1, r2 
                          |
movhi r3, r1              | movgt r3, r1
movhi r4, r2              | movgt r4, r2
movhi r5, #0              | movgt r5, #0
                          |
movls r3, r2              | movle r3, r2

这里我根据所涉及变量的符号给出了两个版本。

movhi 表示如果更高则移动movls 表示如果小于或相同则移动
movgt 表示如果大于则移动movle 表示如果小于或等于则移动
它们意味着相同的算术比较,只是后者对有符号数使用了正确的标志。

我对指令进行了分组,因此很容易识别 if-thenelse 块。
请注意同一块中的指令如何具有相同的后缀(例如 hils)。

真正使这段代码成为 if-then-else 构造而不是其他东西的原因是条件 hi-lsgt-le互斥(两者中只有一个为真)。
所以只能执行一个指令块

使用非互斥条件会产生多个 if-then-else 语句。


如果您误用了术语并且您实际上只想实现一个条件语句(或选择),即一个if-then-else,那么通常的方法是一个 条件分支2 如 Nutan 所示。
这里有一个更易读的版本:

 cmp r1, r2
 bls _A_less_same_B

 mov r3, r1
 mov r4, r2
 eor r5, r5, r5

b _end_if

_A_less_same_B:
 mov r3, r2

_end_if:

将此代码转换为使用有符号整数的负担由您决定。

以冒号 (:) 结尾的花哨的词称为标签,它们是在代码(和数据)中命名点的有用方法3。 将其视为灵活的行号。

b 表示分支,一旦执行,下一条指令将从指定为操作数的标签(地址)中获取(例如来自_end_if)。
bls 是只是一个谓词bbls 表示分支如果小于或相同),通常称为条件分支

条件分支就像普通分支一样,但如果指定的条件不满足,它们可以被“忽略”。
如果条件满足并且 CPU 执行跳转,则称条件跳转被执行,从而从指定为操作数的标签中获取下一条指令。
如果条件不满足并且CPU从分支之后指令继续执行(程序流程通过 em>)。

“条件”通常表示设置和清除标志。 一些指令,如cmp,设置和清除这些标志。
其他指令,如 bls 使用这些标志。

标志保存在专用寄存器中(ARM 中为ps),但有些架构,尤其是 MIPS,没有标志寄存器。

您可以用手指模拟程序流程。比如A > B的流程如下:

                            [Start Here]
                             ¯¯¯¯+¯¯¯¯¯
 cmp r1, r2                      |
 bls _A_less_same_B              + [Branch not taken, fall through]
                                 |
 mov r3, r1                      |
 mov r4, r2                      |
 eor r5, r5, r5                  |
                                 |
b _end_if                        +--[Branch always taken]----+
                                                             |
_A_less_same_B:                                              |
 mov r3, r2                                                  |
                                                             |
_end_if:                         +--[Land here]--------------+
                                 |
                                 V

弯曲的意思是“跳过”我们想要跳过的代码(在本例中为 else)。


我不认识你问题的汇编风格,所以我无法帮助编写具体示例。
无论如何我都不会这样做,因为我觉得这个一般性的解释就足够了,并希望我这样缺乏努力会促使你尝试自己解决这个练习。

这是学习道路上的必经步骤。


1 获取、解码(可能也发出)但仅在设置或清除特定标志时执行的指令。

2 请注意,如果可能,最好避免使用条件分支。根据目标微架构,可能会有更优化的方法来实现相同的结果。这只是值得注意,现在不要理会它。

3 实际上将成为地址的偏移量。

【讨论】:

  • 对于一个不太好的问题,这是一个非常好的答案。干得好!
  • 在 ARM 上,mov r5, #0 是一种更好、更有效的将寄存器归零的方法。不使用xor 感觉很奇怪,但这仅适用于 x86,其中可变长度指令编码意味着避免立即字节实际上节省了空间,并被视为归零习惯用法。在 ARM Thumb2 机器代码中,eor r5,r5 是 4B 指令,但 mov r5, #0 是 2B 指令。此外,eor 将错误地依赖旧值,因为 ARM 微体系结构没有理由将特殊情况 eor same,same 作为归零习惯用法。
  • @PeterCordes 我的直觉告诉我没有零成语,但我懒得去检查。感谢您提供,我正在更新答案。
  • @PeterCordes:比这更糟糕的是:在 ARM 和 POWER 上,指令故意保持依赖以保持内存顺序(这进入了memory_order_consume 领域,这里是龙)。它架构上不是依赖破坏指令。在具有强内存模型的 x86 上,不需要通过数据处理指令来跟踪依赖关系。
  • @EOF:啊,我没有意识到数据依赖的 dep 跟踪是针对弱排序架构(Alpha 除外)记录的。我假设 MIPS 也记录了它。感谢您阐明这一点;我只详细看过英特尔手册,当然没有提到它。如果英特尔 CPU 确实在内部跟踪内存排序的数据依赖关系,我不会感到惊讶,因此它们可以以不影响全局可见排序的方式推测/OOO。无论如何,有趣的是 ARM 在架构上要求不产生异或零中断依赖关系。
猜你喜欢
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多