home | bit manipulation | data manipulation | addressing | loops | conditional execution/flags | about the author
useful documents | exercises | ARMulator | forum | links | c/c++ introduction | contact us | other websites by the author

Current Program State Register

The CPSR (Current Program State Register) is used to keep a note of some important characteristics of the result of an execution. For example if we wanted to implement a FOR loop in C++ we would invariably need a loop counter- i.

for ( i=20; i=0; i--){
//some useful code
}

Here we can see that when i becomes equal to 0 the loop terminates, this is simple in C++ but in ARM assembly it is slightly more difficult- how do we know when i is zero?
This is where the CPSR is used, it keeps a note of the following elements implemented as status bits:
N Negative
Z Zero
C Carry
V Overflow

N Z C V
This is equal to the 32nd bit of the destination register. Remember that the binary values stored in an ARM register can be interpreted as 2s complement format, where a 0 in the MSB indicates +ve and 1 indicates -ve. This is set to 1 when all 32-bits of the destination register are 0, else Z is 0. This is set to 1 when the destination register, as the result of an addition for example, is equal to or greater than ( => ) 2^32. It has more complicated function which will be discussed later. This can be quite complicated but it is generally used to indicate a signed overflow. This assumes however that the registers being used are interpreted as 2s complement. See below.

Detailed Flag Description

The following table describes the most important conditions required to set the flags.
signed/unsigned range flags NZCV
unsigned 2^32 001X
signed/unsigned range flags NZCV
unsigned >2^32 001X
unsigned (2^31)-1 < x < 2^32 1010
unsigned/signed 0 0100

Lets explain some cases in more detail.

Setting C (carry): ADD R0, R1, R2
If the result in R0 is greater than (2^32)-1 given that both R1 and R2 are unsigned C will be set and NZV are 0. Although the ARM registers are 32-bit the highest unsigned value one can express is 2^31 because we start counting from 0.

R1 00000000000000000000111111111111
R2 11111111111111111111000000000000
R0 11111111111111111111111111111111 ADD
Now R0 is 2^31 + 2^30 + 2^29 ... = (2^32)-1, now it is clear to see why any value above this cannot be expressed in 32-bits. So C is set to 1 for values greater than (2^32) -1, try to think of C as the 33rd bit.

Setting C (carry):SIGNED VALUES ADD R0, R1, R2
Where both R1 and R2 are signed. To say that a register is signed just means that we interpret as twos complement. Remenber that in twos complement the MSB is used indicate that the number is negative or positive. But this does mean that we now only have 31-bits to express the magnitude, so the range we can express in 32-bit twos complement is: -2^31< x >+(2^31)-1 . This now means that our maximum value that will trigger C to be set is (2^31)-1.

CMP - COMPARE

Most of the above condition codes compare two values, GT and LO for example. In order to compare a register to a number the CMP or compare instruction is used. The CMP instruction simply subtracts the second operand from the first:
CMP Rn, Rd;
So Rd is subtracted from Rn and the CPSR flags are set automatically and accordingly. This is how two registers are compared. Now from the flag states set by the CMP instruction we can determine a great many things about the relative sizes of those two registers, for example:
If after the CMP instruction the flags are:
This is all very useful, but we want to be able to execute some instructions based on this information. Well in order to do this we need to add the conditional execution mnemonics to our instructions, they are described below.

Conditional Execution

Most ARM assembly instructions can make use of conditional executuion by adding two letters to the end of the instruction as follows: example: ADD(cc) where cc means condition code. The following table describes the most important condition codes.

Mnemonic Flags required for execution Description
GE N == V Greater than or equal to -Signed
GT N == V & (Z Clear) Greater Than -Signed
LT N != V Less Than -Signed
LE (Z set) || (N != V) Less Than -Signed
NE Z clear Not Equal to
HS C set Higher or equal -unsigned
HI C set and Z clear Higher than -unsigned
LS (C clear) || (Z set) Less than or equal to -unsigned
LO C clear Less than -unsigned
EQ Z set EQUAL
PL N clear Positive
CS C set Carry Set
CC C Clear Carry Clear
VS V set Overflow
VC V clear No Overflow
NV N/A NEVER -Probably best not to use
AL N/A Always

To use these all we need to do is add them to the end of the normal instructions, for example:
MOV R0, #10
CMP R0, #10
MOVEQ R1, #1

So here we can see that R0 is made equal to decimal 10, then it is compared to decimal 10, which actually means R0 - 10, which is obviously 0. Because of this the Z flag is set. MOVEQ means MOVE IF EQUAL TO, which if you look in the table above requires that the Z flag is SET. Which is exactly what has happened to us, as a result the register R1 is made equal decimal 1.

Another example is in order.
MOV R0, #10
MOV R1, #1
CMP R0, #20
ADDGE R1, #1

Here R0 is again made equal to decimal 10 and R1 = decimal 1. Now the CMP instruction compares R0 (which is 10) and decimal 20, which actually again actually means R0 - 20 = -10. As a result the N flag is SET. ADDGE translates as ADD IF SIGNED GREATER THAN OR EQUAL . This requires that flags N == V, which is NOT the case here, only the N flag has been set so N != V. This addition does not, therefore go ahead.

The S bit

It is also possible to set the ARM flags using the S bit (which means set bits after execution) after and ADD or a SUB instruction. Example:
MOV R0, #10
SUBS R0, R0, #10
MOVEQ R1, #1

So R0 = 10. SUBS sets the flags after R0 - 10 which == 0, so Z flag SET. The MOVEQ executes because Z SET.

Some more Comparison Instructions

CMN -Is able to set NZCV by instead of subtracting Rn and Rd, but by adding them.
TST - Is only able to set NZ by performing the digital logic operation AND on RN and Rd.
TEQ -Is able to set NZ by performing the XOR or EXCLUSIVE-OR operation on Rn and Rd.
Click Here for a large range of ARM assembly books at low prices!

ARM Assembly Language - an Introduction by J. R. Gibson

ARM Assembly by William Hohl