将c转换为带谓词指令的程序集

将c转换为带谓词指令的程序集,c,assembly,arm,predicates,C,Assembly,Arm,Predicates,我想使用谓词指令将此代码转换为程序集 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

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

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

警告:为新手解答。可能会让有经验的用户厌烦至死


我不确定你是否误用了这个术语,或者你是否真的想用1

在后一种情况下,将其用作研究案例(并继承关于寄存器用法的前提),程序集只需

;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
表示较高时移动<代码>移动表示移动(如果较低或相同)。
movgt
表示较大时移动<代码>移动表示如果小于或等于,则移动。
它们意味着相同的算术比较,只是后者对有符号数字使用了正确的标志

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

使此代码成为if-then-else结构而不是其他结构的真正原因是,条件
hi
-
ls
gt
-
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
表示分支,一旦执行,下一条指令将从指定为操作数的标签(地址)中提取(例如从
\u end\u(如果
)。
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
弯曲意味着“跳过”我们想要跳过的代码(本例中的“跳过”)


我不知道你的问题有多复杂,所以我不能不写具体的例子。
无论如何,我不会这么做,因为我觉得这个一般性的解释已经足够了,希望我这方面的不努力会促使你尝试自己解决这个问题

这是学习过程中的必修课


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

2注意,如果可能,最好避免条件分支。根据目标微结构的不同,可以有一种更为优化的方法来实现相同的结果。这是值得注意的,现在不用麻烦了


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

你在问什么汇编语言?这是对一个不太好的问题的一个非常好的回答。干得好!在ARM上,
movr5,#0
是一种更好、更有效的寄存器归零方法。不使用异或(xor)感觉很奇怪,但这只适用于x86,在x86中,可变长度指令编码意味着避免立即字节实际上节省了空间,并被认为是一种归零习惯用法。在ARM Thumb2机器代码中,
eor r5,r5
是4B指令,而
mov r5,#0
是2B指令。另外,
eor
将对旧值有错误的依赖性,因为没有理由将ARM微体系结构作为特例
eor相同,相同的
作为归零习惯用法。@PeterCordes我的直觉告诉我没有归零习惯用法,但我懒得检查。谢谢提供,我正在更新答案。@PeterCordes:比这更糟:在ARM和POWER上,指令有意保持依赖性以保持内存顺序(这进入
内存\u顺序\u消耗
领域,这里是龙)。它在体系结构上不是一个破坏依赖关系的指令。在具有强内存模型的x86上,依赖项不需要通过数据处理指令进行跟踪。@EOF:ahh,我没有意识到数据依赖项的dep跟踪是针对弱有序体系结构(Alpha除外)进行记录的。我想MIPS也会记录它。谢谢你让我明白这一点;我只看过英特尔手册的细节,当然没有提到。如果Intel CPU在内部跟踪内存排序的数据依赖性,这样他们就可以以不影响全局可见排序的方式推测/OOO,我也不会感到惊讶。无论如何,有趣的是,ARM在体系结构上不需要进行xor归零中断依赖。