使用谓词指令将c转换为程序集

-2 c assembly arm predicates

我想使用谓词指令将此代码转换为汇编

If (A>B){

    C=A;
    D=B;
    E=0

}

else{

    C=B;
} 
Run Code Online (Sandbox Code Playgroud)

它是正确的还是我如何使用跳跃?

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
Run Code Online (Sandbox Code Playgroud)

Mar*_*oom 7

警告:回答新手.可能会让有经验的用户死亡.


我不确定你是否滥用了这个术语,或者你是否真的想要使用谓词指令1.

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

;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
Run Code Online (Sandbox Code Playgroud)

在这里,我根据涉及的变量的符号给出了两个版本.

movhi意味着移动更高.movls意味着移动如果更低或相同.
movgt意味着移动更大.movle意味着移动,如果更少或相等.
它们意味着相同的算术比较,只是后者使用适当的标志来签名数字.

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

真正使这个代码的if-then-else的构造,而不是别的东西是事实的条件hi- lsgt- le相互排斥的(只有三三两两的人可以是真实的).
因此,只能执行一个指令块.

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


如果您滥用术语并且您实际上只想实现条件语句(或选择),即if-then-else,则通常的方法是Nutan已经显示的条件分支2.
这里有一个稍微可读的版本:

 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:
Run Code Online (Sandbox Code Playgroud)

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

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

b表示分支,一旦执行,下一条指令就从指定为操作数的标签(地址)中取出(例如从_end_if).
bls只是一个谓词b(bls意味着分支,如果更少或相同),通常称为条件分支.

条件分支就像普通分支一样,但如果指定的条件无法满足,则可以"忽略"它们.
条件跳转被说成是采取如果条件满足并且CPU执行该跳跃,从而获取从指定为操作数的标签的下一个指令.
它被说成是不采取如果条件不满足,并且CPU继续从指令执行分支(程序流落空).

"条件"通常表示设置和清除标志.一些指令,如cmp设置和清除这些标志.
其他说明,比如bls使用这些标志.

标志保存在专用寄存器中(ps在ARM中),但有一些架构,最明显的是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
Run Code Online (Sandbox Code Playgroud)

弯曲意味着画出"跳过"我们想要跳过的代码(在这种情况下为其他).


我不承认你的问题的集合味道,所以我无法帮助编写具体的例子.
我不会这样做,因为我觉得这个一般的解释是足够的,并希望我这样的努力不足会刺激你自己尝试解决这个问题.

这是学习路线上的必修课.


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

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

3实际上会成为地址的偏移量.

  • 对于一个不那么好的问题,这是一个非常好的答案.不错的工作! (4认同)
  • 在ARM上,`mov r5,#0`是一种更好,更有效的归零寄存器方法.不使用`xor`感觉很奇怪,但这只适用于x86,其中可变长度指令编码意味着避免立即字节实际上节省了空间,并被识别为归零成语.在ARM Thumb2机器代码中,`eor r5,r5`是4B指令,但`mov r5,#0`是2B指令.此外,`eor`将对旧值具有错误的依赖性,因为没有理由将ARM微体系结构与特殊情况"相同",与归零成语相同. (3认同)
  • @PeterCordes:比这更糟糕:在ARM和POWER上,指令被有意保持依赖以保持内存排序(这进入`memory_order_consume`领域,这里是龙).它在架构上*不是依赖性破坏指令.在具有强大内存模型的x86上,不需要通过数据处理指令跟踪依赖性. (2认同)