这个ARM汇编代码程序执行后如何找到N,C,Z,V标志位?
How to find N,C,Z,V flags after the execution of this ARM assembly code program?
给出以下 ARM 汇编代码,找到 ALU 标志的输出 [Negative, Carry out, Zero, oVerflow]
MOV R0 #00000100
MOV R1 #00000100
MOV R2 #0000010A
CMP R0, R1
SUBGES R0, R0, R2
ADDLTS R0, R1, R2
正确答案应该是N=1; C=V=Z=0 但我不确定。另外,我什至不确定 #00000100
是二进制、十进制还是十六进制。
不管怎样,考虑到它们都是十六进制的,我是这样处理的:
CMP R0 R1
给出 ALU 标志 Z=1 和 C=V=N=0。
SUBGES R0, R0, R2
如果 "Greater or equal" 执行减法(检查是否 N==V)。由于 N=V,
R0-R2 = 256 - 266 = -10
回想一下 "S" uodates 标志,N=1,C=Z=V=0。
ADDLTS R0, R1, R2
如果 "Less Than" 执行加法(检查是否 N!=V)。由于 N!=V,
R1 + R2 = 256 + 266 = 522
表示N=C=Z=V=0.
我哪里错了?
如果指令是 subge
和 addlt
, 正确的 答案是有意义的。很少(但有可能)有条件和集合。通常这是一个错误。例如,参见下面来自 David Seal 的 ARM ARM 第二版的示例,
/* C code for Euclid’s Greatest Common Divisor (GCD)*/
/* Returns the GCD of its two parameters */
int gcd(int a, int b)
{
while (a != b)
if (a > b )
a = a - b ;
else
b = b - a ;
return a ;
}
; ARM assembler code for Euclid’s Greatest Common Divisor
; On entry: R0 holds ‘a’, R1 holds ‘b’
; On exit : R0 hold GCD of A and B
gcd:
CMP R0, R1 ; compare ‘a’ and ‘b’
SUBGT R0, R0, R1 ; if (a>b) a=a-b (if a==b do nothing)
SUBLT R1, R1, R0 ; if (b>a) b=b-a (if a==b do nothing)
BNE gcd ; if (a!=b) then keep going
MOV PC, LR ; return to caller
这是非常密集的代码,既可以有条件地执行又可以设置标志。一个明显的计数器是(也来自 ARM ARM 第 2 版),
if (a==0 || b==1)
c = d + e ;
CMP R0, #0 ; compare a with 0
CMPNE R1, #1 ; if a is not 0, compare b to 1
ADDEQ R2, R3, R4 ; if either was true c = d + e
如果您的问题全部正确,那么正确答案就是错误的。
CMP R0, R1
SUBGES R0, R0, R2
ADDLTS R0, R1, R2 ; why bother setting conditions here?
这映射到,
if(a <= b) {
if(a <= c)
a = b + c;
else
/* a = a */ ;
} else {
a = a - c;
}
将 a <= b && a > c
保留为原始 a
。这是可能的,但似乎有点做作。表格,
CMP R0, R1
SUBGE R0, R0, R2
ADDLT R0, R1, R2
实用多了。如果不知何故这是带有前面 IT
的 Thumb2 代码,而您错过了对它的反汇编,那么反汇编将 subge
显示为 subs
如果事情是正确的。这可能是某种反汇编程序错误;但这似乎是纸笔作业题。我想这里的一点是,在 Thumb2 和统一汇编器中,这些形式 (subges
/addlts
) 甚至是不允许的。
更新给可能对此问题感兴趣的人:
我的教授犯了一个错误,仅此而已。正确答案是我写的
给出以下 ARM 汇编代码,找到 ALU 标志的输出 [Negative, Carry out, Zero, oVerflow]
MOV R0 #00000100
MOV R1 #00000100
MOV R2 #0000010A
CMP R0, R1
SUBGES R0, R0, R2
ADDLTS R0, R1, R2
正确答案应该是N=1; C=V=Z=0 但我不确定。另外,我什至不确定 #00000100
是二进制、十进制还是十六进制。
不管怎样,考虑到它们都是十六进制的,我是这样处理的:
CMP R0 R1
给出 ALU 标志 Z=1 和 C=V=N=0。
SUBGES R0, R0, R2
如果 "Greater or equal" 执行减法(检查是否 N==V)。由于 N=V,
R0-R2 = 256 - 266 = -10
回想一下 "S" uodates 标志,N=1,C=Z=V=0。
ADDLTS R0, R1, R2
如果 "Less Than" 执行加法(检查是否 N!=V)。由于 N!=V,
R1 + R2 = 256 + 266 = 522
表示N=C=Z=V=0.
我哪里错了?
如果指令是 subge
和 addlt
, 正确的 答案是有意义的。很少(但有可能)有条件和集合。通常这是一个错误。例如,参见下面来自 David Seal 的 ARM ARM 第二版的示例,
/* C code for Euclid’s Greatest Common Divisor (GCD)*/
/* Returns the GCD of its two parameters */
int gcd(int a, int b)
{
while (a != b)
if (a > b )
a = a - b ;
else
b = b - a ;
return a ;
}
; ARM assembler code for Euclid’s Greatest Common Divisor
; On entry: R0 holds ‘a’, R1 holds ‘b’
; On exit : R0 hold GCD of A and B
gcd:
CMP R0, R1 ; compare ‘a’ and ‘b’
SUBGT R0, R0, R1 ; if (a>b) a=a-b (if a==b do nothing)
SUBLT R1, R1, R0 ; if (b>a) b=b-a (if a==b do nothing)
BNE gcd ; if (a!=b) then keep going
MOV PC, LR ; return to caller
这是非常密集的代码,既可以有条件地执行又可以设置标志。一个明显的计数器是(也来自 ARM ARM 第 2 版),
if (a==0 || b==1)
c = d + e ;
CMP R0, #0 ; compare a with 0
CMPNE R1, #1 ; if a is not 0, compare b to 1
ADDEQ R2, R3, R4 ; if either was true c = d + e
如果您的问题全部正确,那么正确答案就是错误的。
CMP R0, R1
SUBGES R0, R0, R2
ADDLTS R0, R1, R2 ; why bother setting conditions here?
这映射到,
if(a <= b) {
if(a <= c)
a = b + c;
else
/* a = a */ ;
} else {
a = a - c;
}
将 a <= b && a > c
保留为原始 a
。这是可能的,但似乎有点做作。表格,
CMP R0, R1
SUBGE R0, R0, R2
ADDLT R0, R1, R2
实用多了。如果不知何故这是带有前面 IT
的 Thumb2 代码,而您错过了对它的反汇编,那么反汇编将 subge
显示为 subs
如果事情是正确的。这可能是某种反汇编程序错误;但这似乎是纸笔作业题。我想这里的一点是,在 Thumb2 和统一汇编器中,这些形式 (subges
/addlts
) 甚至是不允许的。
更新给可能对此问题感兴趣的人:
我的教授犯了一个错误,仅此而已。正确答案是我写的