Reputation: 562
Giving the following ARM assembly code, find the the output of the ALU flags [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
The correct answer should be N=1 ; C=V=Z=0 but I'm not sure about it. Also, I'm not even sure if #00000100
is binary, decimal or hexadecimal.
Anyways, considering all of them hexadecimal, I'm proceeding in this way:
CMP R0 R1
Gives as ALU flags Z=1 and C=V=N=0.
SUBGES R0, R0, R2
performs a subtracion if "Greater or equal" (checks if N==V). Since N=V,
R0-R2 = 256 - 266 = -10
Recall that "S" uodates flags, N=1, C=Z=V=0.
ADDLTS R0, R1, R2
performs an addition if "Less Than" (checks if N!=V). Since N!=V,
R1 + R2 = 256 + 266 = 522
It means that N=C=Z=V=0.
Where am I wrong?
Upvotes: 1
Views: 2634
Reputation: 562
Update for those who may be interested in this question:
My professor made a mistake, that's all. The correct answer is that I wrote.
Upvotes: 0
Reputation: 22395
The correct answer makes sense if the instructions are subge
and addlt
. It is rare (but is possible) to have a conditional and set. Usually this would be an error. See for instance the example below from the ARM ARM 2nd edition by David Seal,
/* 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
It is very dense code that would both execute conditionally and set flags. An obvious counter is (also from ARM ARM 2nd edition),
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
If everything in your question is correct, then the correct answer is wrong.
CMP R0, R1
SUBGES R0, R0, R2
ADDLTS R0, R1, R2 ; why bother setting conditions here?
This maps to,
if(a <= b) {
if(a <= c)
a = b + c;
else
/* a = a */ ;
} else {
a = a - c;
}
which leaves the case a <= b && a > c
as the original a
. It is possible, but it seems a little contrived. The form,
CMP R0, R1
SUBGE R0, R0, R2
ADDLT R0, R1, R2
Is much more practical. If somehow this is Thumb2 code with a preceding IT
, and you missed disassembling it, then disassembly will present subge
as subs
if things are correct. It could be some sort of disassembler bug; but it seems like a paper and pencil homework question. I guess a point here is that in Thumb2 and unified assembler, these forms (subges
/addlts
) aren't even allowed.
Upvotes: 1