If else OR statement in Assembly?
If else OR statement in Assembly?
对在 Assembly 中使用分支命令感到困惑,主要是 BNE
和 BEQ
。
所以我要为伪代码写一个汇编代码:
X = 5, Y = 10, Z = 15
if X != 4 && Y == 10 || Z = 20
A = X + Y - 2
else R = Z - 5 + X
我在 Keil uVision5 中为 ARM Cortex M0 Plus(不知道是否需要此信息)在其低位寄存器中编码,对于这个特定的板来说是 R0-R7 .
我知道如何编写 if else
语句本身,但我主要想问的是如何处理代码的 OR
部分。很明显 X!=4
为真, Y==10
为真,然后检查 Z = 20
是否为假,所以我会先检查 X!=4
,使用 [=12 跳转=] 标签来检查 Y,使用 BEQ
来检查 Z,这是错误的,但由于等式已经正确,我会跳到 BNE
endif 语句 A=X+Y-2
?
然后在前面没有标签的情况下,如果第一个 BNE 标签不知何故是错误的,我会编写 else 语句供汇编器使用..?
A EQU 0x2000000
R EQU 0x2000004
X EQU 0x2000008
Y EQU 0x200000C
Z EQU 0x2000010
LDR R7, =X
LDR R0, [R7]
ADD R0, #5 ; X = 5 in R0
CMP R0, #4 ; Compare X != 4
BNE jumpToY
jumpToY
LDR R7, =Y
LDR R1, [R7] ; Y = 10 in R1
CMP R1, #10 ; Compare Y == 10
BEQ jumpToZ
jumpToZ
etc...
想想你是如何评估头脑中的逻辑条件的。如果你想要A或B而你得到了A那么你就不需要考虑B。如果你想要A和B而你没有A那么计算B就没有意义了。
有些纯粹主义者认为您应该评估这两个条件,然后对结果进行逻辑比较:
计算一个
计算 B
AND/OR结果一起
幸运的是,工程方法胜出:
对于 A 和 B(假设 BEQ 是 "true"):
Calculate A
BNE fail
Calculate B
BNE fail
success:
...
RET/JMP somewhere ; Don't drop through into fail
fail:
...
对于 A OR B(同样,假设 BEQ 是 "true"):
Calculate A
BEQ success
Calculate B
BNE fail
success:
...
RET/JMP somewhere ; Don't drop through into fail
fail:
...
A EQU 0x2000000
R EQU 0x2000004
X EQU 0x2000008
Y EQU 0x200000C
Z EQU 0x2000010
在这里,您可以看到防止额外跳转的条件指令。我们首先检查 And 的前 2 种情况,然后默认为 Or 情况。另请注意,我们必须跳到 else 代码之外以防止两者都执行。另请注意,我们进入了 else 案例,也是为了防止额外的跳转。
; These could be loaded with a singl LDM instruction instead.
LDR R7, =X
LDR R0, [R7]
LDR R7, =Y
LDR R0, [R7]
LDR R7, =Z
LDR R2, [R7]
CMP R0,#5
CMPEQ R1,#10
BEQ FirstCase
CMP R2,#5
BEQ FirstCase
;... Fall Through
ElseCase:
...
j RestOfCode
FirstCase:
...
RestOfCode:
请注意我是盲目编码的,这对任何语言来说都是危险的事情,ASM 更是如此。它应该演示如何处理您想要查看的 And/Or 个案例。
您还可以将代码放入 C 编译器并检查输出,因为它也会显示工作代码。
对于使用由一条指令设置的标志,然后是条件指令分支或跳转的处理器,asm 通常如何工作。在 branch/jump 条件之前的某个时刻,您设置了标志,例如比较在这种情况下会这样做。条件分支指令的工作方式是,如果条件为真,它会分支到该地址,这与 goto 在 C 中的工作方式完全相同。如果条件不为真,则不会。
if(x!=4) goto label0;
label2:
if(z==20) goto label1;
R = Z - 5 + X;
goto done;
label0:
if(y!=10) goto label2:
...
done:
所以从顶部开始,如果 x 不是 4,那么我们分支到 label0 并执行那里的操作,如果它是 4,那么我们继续执行 if z==20
然后重新关注 z==20 如果 z==20 则转到 label1 否则继续进行计算。
在汇编中类似于
ldr r0,=X
ldr r0,[r0]
cmp r0,#4
bne label0
ldr r2,=Z
ldr r2,[r2]
cmp r2,#20
beq label1
sub r2,#5
add r0,r2
ldr r2,=X
str r0,[r2]
b done
label0:
ldr r1,=Y
ldr r1,[r1]
cmp r1,#10
bne label2:
...
done:
我没有特别的原因在分支后面加了空格。在第一个 bne label0 上,如果确实发生了,那么我们接下来执行标签 0 之后的内容,如果设置了相等标志,则加载 y 地址,然后我们不分支,我们继续执行 Z 地址的加载。
就覆盖逻辑路径而言,可能会使你自己成为一个真理 table X!=4 Y==10 和 Z==20 中的每一个都是真或假,结果要么是 R=或 A=,然后您可以在最坏的情况下从字面上执行真相 table(8 组比较)或缩小范围……并继续优化直到您满意为止。
最终你希望 A= 代码在某个地方有一个分支到函数的末尾,而 R= 代码在某个地方也有一个分支到函数的末尾,然后根据你的真相 table 和实现您创建路径以获取 A= 或 R= 代码,但您必须点击其中一个。
编辑:
注意你的前三行看起来不对
LDR R7, =X
LDR R0, [R7]
ADD R0, #5 ; X = 5 in R0
这不是将 X 设置为 5,因为您的评论暗示它会将 5 添加到 X,因此无论 X 是什么,您都添加了 5。
如果你想实现这个 X = 5, Y = 10, Z = 15
ldr r1,=X
mov r0,#5
str r0,[r1]
ldr r1,=Y
mov r0,#10
str r0,[r1]
ldr r1,=Z
mov r0,#15
str r0,[r1]
然后获取 x 并进行比较
LDR R7, =X
LDR R0, [R7]
CMP R0, #4 ; Compare X != 4
对在 Assembly 中使用分支命令感到困惑,主要是 BNE
和 BEQ
。
所以我要为伪代码写一个汇编代码:
X = 5, Y = 10, Z = 15
if X != 4 && Y == 10 || Z = 20
A = X + Y - 2
else R = Z - 5 + X
我在 Keil uVision5 中为 ARM Cortex M0 Plus(不知道是否需要此信息)在其低位寄存器中编码,对于这个特定的板来说是 R0-R7 .
我知道如何编写 if else
语句本身,但我主要想问的是如何处理代码的 OR
部分。很明显 X!=4
为真, Y==10
为真,然后检查 Z = 20
是否为假,所以我会先检查 X!=4
,使用 [=12 跳转=] 标签来检查 Y,使用 BEQ
来检查 Z,这是错误的,但由于等式已经正确,我会跳到 BNE
endif 语句 A=X+Y-2
?
然后在前面没有标签的情况下,如果第一个 BNE 标签不知何故是错误的,我会编写 else 语句供汇编器使用..?
A EQU 0x2000000
R EQU 0x2000004
X EQU 0x2000008
Y EQU 0x200000C
Z EQU 0x2000010
LDR R7, =X
LDR R0, [R7]
ADD R0, #5 ; X = 5 in R0
CMP R0, #4 ; Compare X != 4
BNE jumpToY
jumpToY
LDR R7, =Y
LDR R1, [R7] ; Y = 10 in R1
CMP R1, #10 ; Compare Y == 10
BEQ jumpToZ
jumpToZ
etc...
想想你是如何评估头脑中的逻辑条件的。如果你想要A或B而你得到了A那么你就不需要考虑B。如果你想要A和B而你没有A那么计算B就没有意义了。
有些纯粹主义者认为您应该评估这两个条件,然后对结果进行逻辑比较: 计算一个 计算 B AND/OR结果一起
幸运的是,工程方法胜出:
对于 A 和 B(假设 BEQ 是 "true"):
Calculate A
BNE fail
Calculate B
BNE fail
success:
...
RET/JMP somewhere ; Don't drop through into fail
fail:
...
对于 A OR B(同样,假设 BEQ 是 "true"):
Calculate A
BEQ success
Calculate B
BNE fail
success:
...
RET/JMP somewhere ; Don't drop through into fail
fail:
...
A EQU 0x2000000
R EQU 0x2000004
X EQU 0x2000008
Y EQU 0x200000C
Z EQU 0x2000010
在这里,您可以看到防止额外跳转的条件指令。我们首先检查 And 的前 2 种情况,然后默认为 Or 情况。另请注意,我们必须跳到 else 代码之外以防止两者都执行。另请注意,我们进入了 else 案例,也是为了防止额外的跳转。
; These could be loaded with a singl LDM instruction instead.
LDR R7, =X
LDR R0, [R7]
LDR R7, =Y
LDR R0, [R7]
LDR R7, =Z
LDR R2, [R7]
CMP R0,#5
CMPEQ R1,#10
BEQ FirstCase
CMP R2,#5
BEQ FirstCase
;... Fall Through
ElseCase:
...
j RestOfCode
FirstCase:
...
RestOfCode:
请注意我是盲目编码的,这对任何语言来说都是危险的事情,ASM 更是如此。它应该演示如何处理您想要查看的 And/Or 个案例。
您还可以将代码放入 C 编译器并检查输出,因为它也会显示工作代码。
对于使用由一条指令设置的标志,然后是条件指令分支或跳转的处理器,asm 通常如何工作。在 branch/jump 条件之前的某个时刻,您设置了标志,例如比较在这种情况下会这样做。条件分支指令的工作方式是,如果条件为真,它会分支到该地址,这与 goto 在 C 中的工作方式完全相同。如果条件不为真,则不会。
if(x!=4) goto label0;
label2:
if(z==20) goto label1;
R = Z - 5 + X;
goto done;
label0:
if(y!=10) goto label2:
...
done:
所以从顶部开始,如果 x 不是 4,那么我们分支到 label0 并执行那里的操作,如果它是 4,那么我们继续执行 if z==20 然后重新关注 z==20 如果 z==20 则转到 label1 否则继续进行计算。
在汇编中类似于
ldr r0,=X
ldr r0,[r0]
cmp r0,#4
bne label0
ldr r2,=Z
ldr r2,[r2]
cmp r2,#20
beq label1
sub r2,#5
add r0,r2
ldr r2,=X
str r0,[r2]
b done
label0:
ldr r1,=Y
ldr r1,[r1]
cmp r1,#10
bne label2:
...
done:
我没有特别的原因在分支后面加了空格。在第一个 bne label0 上,如果确实发生了,那么我们接下来执行标签 0 之后的内容,如果设置了相等标志,则加载 y 地址,然后我们不分支,我们继续执行 Z 地址的加载。
就覆盖逻辑路径而言,可能会使你自己成为一个真理 table X!=4 Y==10 和 Z==20 中的每一个都是真或假,结果要么是 R=或 A=,然后您可以在最坏的情况下从字面上执行真相 table(8 组比较)或缩小范围……并继续优化直到您满意为止。
最终你希望 A= 代码在某个地方有一个分支到函数的末尾,而 R= 代码在某个地方也有一个分支到函数的末尾,然后根据你的真相 table 和实现您创建路径以获取 A= 或 R= 代码,但您必须点击其中一个。
编辑:
注意你的前三行看起来不对
LDR R7, =X
LDR R0, [R7]
ADD R0, #5 ; X = 5 in R0
这不是将 X 设置为 5,因为您的评论暗示它会将 5 添加到 X,因此无论 X 是什么,您都添加了 5。
如果你想实现这个 X = 5, Y = 10, Z = 15
ldr r1,=X
mov r0,#5
str r0,[r1]
ldr r1,=Y
mov r0,#10
str r0,[r1]
ldr r1,=Z
mov r0,#15
str r0,[r1]
然后获取 x 并进行比较
LDR R7, =X
LDR R0, [R7]
CMP R0, #4 ; Compare X != 4