Part 11 – Linux ARM assembly Execution branch

In 32-bit ARM architecture systems, there is a special general purpose register, r15, which is also a PC register.

PC is program Counter. Also called IP, Instruction pointer.

When an ARM processor executes an instruction, two things can happen at the end of its execution. If the instruction does not modify the PC, the PC will only increase by 4, because in 32-bit ARM, the instruction is 32 bits wide, so there are 4 bytes between each instruction. If the instruction modifies PC, the new value of PC is used. Of course 64-bit ARM is increased by 8 after each instruction.

If one instruction does change PC to something other than, say, PC + 4, then another instruction of that program can be run. The process of changing PC values is called branching. In ARM, this is done using the branch instruction.

There are unconditional branches and conditional branches.

Unconditional branches are forced jumps, so let’s focus on conditional branches.

Conditional branch

Here a Register CPSR (Urrent Program Status Register) is involved.

It contains the conditional flag:

N (negative), Z (zero), C (carry) and V (overflow)

N: If the result of the command is negative, it is enabled. Otherwise, it is disabled.

Z: Enabled if the result of the instruction is zero. If it is non-zero, disable it.

C: C is enabled if the resulting value of the instruction needs to represent bit 33 exactly. For example, addition overflows the range of 32-bit integers. For subtraction, there is a special case where no borrowing subtraction enables C, otherwise it is disabled: otherwise, reducing a larger number to a smaller value will enable C, but if vice versa, it will be disabled.

V: If the resulting value of the instruction cannot be represented in 32-bit binary complement, V is enabled.

Assembly instruction

EQ (equal) Z is 1NE (not equal) Z is 0GE (greater than or equal to, represented by two complements). When V = N. LT (lower than, two complements). This is the opposite of GE, where V does not equal N to GT (greater than, is two complement). Z=0, N=VLE (less than or equal to, denoted by two complements). Z=0 or V does not equal NMI (negative/negative) N is 1PL (positive/positive or zero) N is 0VS (overflow set) V is 1VC (clear overflow) V is 0HI (higher) C is 1 and Z is 0LS (lower or same) C is 0 or Z is 1CS/HS (carry set/higher or same) when C is 1CC / LO (carry clear/drop) when C is 0

32 sample

.text .global main main: Mov R1, #2 /* R1 ← 2 */ mov R2, #2 /* R2 ← 2 */ CMP R1, r2 /* update cpsr condition codes with the value of r1-r2 */ beq case_equal /* branch to case_equal only if Z = 1 */ Case_different: mov r0, #2 /* R0 ← 2 */ b end /* branch to end */ case_equal: mov R0, #1 /* R0 ← 1 */ end: bx lrCopy the code

as -g -o com.o com.s

ld -o com com.o

The jump occurs when registers R1 and R2 are equal.

64 sample

Let’s take a look at the 64-bit sample code.

.arch armv8-a .global _start .text _start: Mov x1, #2 /* R1 ← 2 */ mov x2, #2 /* R2 ← 2 */ CMP x1, x2 /* update cpsr condition codes with the value of r1-r2 */ beq case_equal /* branch to case_equal only if Z = 1 */ Case_different: mov x0, #2 /* R0 ← 2 */ b end /* branch to end */ case_equal: mov x0, #1 /* R0 ← 1 */ mov x8, 93 SVC 0Copy the code

as -g -o com64.o com64.s

ld -o com64 com64.o