Chapter 3: Basic ARM64 Instructions
3.1 What are Instructions?
Instructions are the basic commands that tell the computer what to do. Each instruction is a simple operation the processor can execute.
An instruction typically has two parts:
The operation (what to do)
The operands (what to do it with)
Example:
MOV: operation (move data)
x0: destination operand
#42: source operand
Main Categories of ARM64 Instructions
ARM64 has several categories of instructions. We'll cover the following:
Data Processing Instructions
Perform operations on data in registers
Examples: ADD, SUB, AND, ORR
Memory Instructions
Move data between registers and memory
Examples: LDR (load), STR (store)
Branch Instructions
Control program flow
Examples: B (branch), BL (branch with link)
System Instructions
Interact with system features
Examples: SVC (supervisor call)
In the following sections, we'll explore each of these categories in detail, starting with Data Processing Instructions. We'll explain what each category does, provide examples, and show how they're used in real ARM64 assembly programming.
3.2 Data Processing Instructions
Data Processing Instructions are fundamental operations in ARM64 assembly. They manipulate data within registers, forming the core of most computational tasks.
3.2.1 Integer Arithmetic
Arithmetic instructions perform basic mathematical operations on register values.
ADD (Addition)
This instruction adds the values in registers Xn and Xm, storing the result in Xd.
Example:
Explanation: If X1 contains 5 and X2 contains 3, after this instruction, X0 will contain 8.
Answer:
Before: X1 = 5, X2 = 3
After: X0 = 8 (5 + 3)
The ADD instruction is used for simple addition. It's commonly used in loops, array indexing, and general arithmetic calculations.
SUB (Subtraction)
This instruction subtracts the value in Xm from Xn, storing the result in Xd.
Example:
Explanation: If X1 contains 10 and X2 contains 7, after this instruction, X0 will contain 3.
Answer:
Before: X1 = 10, X2 = 7
After: X0 = 3 (10 - 7)
SUB is used for subtraction operations. It's often used in comparison operations, decrementing counters, and calculating differences.
MUL (Multiplication)
This instruction multiplies the values in Xn and Xm, storing the result in Xd.
Example:
Explanation: If X1 contains 6 and X2 contains 4, after this instruction, X0 will contain 24.
Answer:
Before: X1 = 6, X2 = 4
After: X0 = 24 (6 * 4)
MUL is used for multiplication. It's common in mathematical computations, scaling values, and implementing algorithms that require multiplication.
SDIV (Signed Division)
This instruction divides Xn by Xm (treating them as signed integers), storing the quotient in Xd.
Example:
Explanation: If X1 contains 15 and X2 contains 3, after this instruction, X0 will contain 5.
Answer:
Before: X1 = 15, X2 = 3
After: X0 = 5 (15 / 3)
SDIV is used for integer division. It's important to note that this instruction handles signed division, meaning it works correctly with both positive and negative numbers.
Sure, let's add more detailed explanations of the basic concepts for each logical instruction along with the examples.
Let's break down the instructions with simpler and more detailed explanations using small numbers and binary representation to make it clearer.
3.2.2 Logical Instructions
AND Instruction
The AND instruction performs a bitwise AND between two registers. Each bit of the result is 1 if the corresponding bits of both operands are 1; otherwise, it is 0.
Syntax
Rd: Destination register.
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will perform a bitwise AND operation between the values in registers X2 and X3 and store the result in X1.
Explanation
Let's assume:
X2 = 0x2 (in binary: 0010, in decimal: 2)
X3 = 0x3 (in binary: 0011, in decimal: 3)
Bitwise AND operation:
Result stored in X1: 0x2 (2 in decimal)
ORR Instruction
The ORR instruction performs a bitwise OR between two registers. Each bit of the result is 1 if the corresponding bit of either operand is 1.
Syntax
Rd: Destination register.
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will perform a bitwise OR operation between the values in registers X2 and X3 and store the result in X1.
Explanation
Let's assume:
X2 = 0x2 (in binary: 0010, in decimal: 2)
X3 = 0x3 (in binary: 0011, in decimal: 3)
Bitwise OR operation:
Result stored in X1: 0x3 (3 in decimal)
EOR Instruction
The EOR instruction performs a bitwise Exclusive OR (XOR) between two registers. Each bit of the result is 1 if the corresponding bits of the operands are different; otherwise, it is 0.
Syntax
Rd: Destination register.
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will perform a bitwise XOR operation between the values in registers X2 and X3 and store the result in X1.
Explanation
Let's assume:
X2 = 0x2 (in binary: 0010, in decimal: 2)
X3 = 0x3 (in binary: 0011, in decimal: 3)
Bitwise XOR operation:
Result stored in X1: 0x1 (1 in decimal)
BIC Instruction
The BIC instruction performs a bitwise AND NOT operation between two registers. It clears the bits of the first operand that are set in the second operand.
Syntax
Rd: Destination register.
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will clear the bits in X2 that are set in X3 and store the result in X1.
Explanation
Let's assume:
X2 = 0x3 (in binary: 0011, in decimal: 3)
X3 = 0x2 (in binary: 0010, in decimal: 2)
Bitwise AND NOT operation:
Result stored in X1: 0x1 (1 in decimal)
ORN Instruction
The ORN instruction performs a bitwise OR NOT operation between two registers.
Syntax
Rd: Destination register.
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will perform a bitwise OR operation between X2 and the bitwise NOT of X3 and store the result in X1.
Explanation
Let's assume:
X2 = 0x1 (in binary: 0001, in decimal: 1)
X3 = 0x2 (in binary: 0010, in decimal: 2)
Bitwise OR NOT operation:
Result stored in X1: 0xD (13 in decimal)
EON Instruction
The EON instruction performs a bitwise Exclusive OR NOT operation between two registers.
Syntax
Rd: Destination register.
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will perform a bitwise XOR operation between X2 and the bitwise NOT of X3 and store the result in X1.
Explanation
Let's assume:
X2 = 0x1 (in binary: 0001, in decimal: 1)
X3 = 0x2 (in binary: 0010, in decimal: 2)
Bitwise XOR NOT operation:
Result stored in X1: 0xC (12 in decimal)
3.2.3 Comparison Instructions
Comparison instructions are used to compare the values of two registers. The result of the comparison affects the condition flags (N, Z, C, V), which can be used in subsequent conditional instructions. The main comparison instructions in ARM64 are:
CMP - Compare
CMN - Compare Negative
CMP Instruction
The CMP (Compare) instruction compares the values of two registers by subtracting the second operand from the first operand. It sets the condition flags based on the result, but does not store the result.
Syntax
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will compare the values in registers X2 and X3 by performing the operation X2 - X3.
Explanation
Let's assume:
X2 = 0x5 (5 in decimal)
X3 = 0x3 (3 in decimal)
The comparison will perform:
This is:
The condition flags are set as follows:
N (Negative): 0 (result is not negative)
Z (Zero): 0 (result is not zero)
C (Carry): 1 (no borrow, means X2 >= X3)
V (Overflow): 0 (no overflow)
CMN Instruction
The CMN (Compare Negative) instruction compares the values of two registers by adding the second operand to the first operand. It sets the condition flags based on the result, but does not store the result.
Syntax
Rn: First operand register.
Rm: Second operand register.
Example
This instruction will compare the values in registers X2 and X3 by performing the operation X2 + X3.
Explanation
Let's assume:
X2 = 0x2 (2 in decimal)
X3 = 0x3 (3 in decimal)
The comparison will perform:
This is:
The condition flags are set as follows:
N (Negative): 0 (result is not negative)
Z (Zero): 0 (result is not zero)
C (Carry): 0 (irrelevant in addition)
V (Overflow): 0 (no overflow)
3.2.4 Shift Instructions
Shift instructions are used to shift the bits in a register to the left or right. The main shift instructions in ARM64 are:
LSL - Logical Shift Left
LSR - Logical Shift Right
ASR - Arithmetic Shift Right
LSL Instruction
The LSL (Logical Shift Left) instruction shifts the bits of a register to the left by a specified number of positions. Zeros are shifted into the least significant bits.
Syntax
Rd: Destination register.
Rn: Source register.
shift: Number of positions to shift.
Example
This instruction will shift the bits in register X2 to the left by 2 positions and store the result in X1.
Explanation
Let's assume:
X2 = 0x2 (0010 in binary, 2 in decimal)
Logical Shift Left by 2 positions:
Result stored in X1: 0x8 (8 in decimal)
LSR Instruction
The LSR (Logical Shift Right) instruction shifts the bits of a register to the right by a specified number of positions. Zeros are shifted into the most significant bits.
Syntax
Rd: Destination register.
Rn: Source register.
shift: Number of positions to shift.
Example
This instruction will shift the bits in register X2 to the right by 2 positions and store the result in X1.
Explanation
Let's assume:
X2 = 0x8 (1000 in binary, 8 in decimal)
Logical Shift Right by 2 positions:
Result stored in X1: 0x2 (2 in decimal)
ASR Instruction
The ASR (Arithmetic Shift Right) instruction shifts the bits of a register to the right by a specified number of positions. The most significant bit (sign bit) is replicated into the shifted positions.
Syntax
Rd: Destination register.
Rn: Source register.
shift: Number of positions to shift.
Example
This instruction will shift the bits in register X2 to the right by 2 positions and store the result in X1.
Explanation
Let's assume:
X2 = 0xF8 (1111 1000 in binary, -8 in decimal using two's complement for negative numbers)
Arithmetic Shift Right by 2 positions:
Result stored in X1: 0xFE (-2 in decimal)
3.2.5 Rotate Instructions
Rotate instructions are used to rotate the bits in a register around the end of the register. The main rotate instructions in ARM64 are:
ROR - Rotate Right
ROL - Rotate Left (not directly available in ARM64, can be achieved using ROR and appropriate shifts)
ROR Instruction
The ROR (Rotate Right) instruction rotates the bits of a register to the right by a specified number of positions. Bits shifted out of the least significant bit position are rotated back into the most significant bit position.
Syntax
Rd: Destination register.
Rn: Source register.
shift: Number of positions to rotate.
Example
This instruction will rotate the bits in register X2 to the right by 2 positions and store the result in X1.
Explanation
Let's assume:
X2 = 0xB (1011 in binary, 11 in decimal)
Rotate Right by 2 positions:
Result stored in X1: 0xE (14 in decimal)
ROL Instruction
The ROL (Rotate Left) instruction is not directly available in ARM64, but it can be achieved using the ROR instruction and appropriate shifts. Rotate Left by N positions is equivalent to Rotate Right by (32-N) positions.
Example
This sequence of instructions will rotate the bits in register X2 to the left by 2 positions and store the result in X1.
Explanation
Let's assume:
X2 = 0xB (1011 in binary, 11 in decimal)
Rotate Left by 2 positions:
Logical Shift Left by 2 positions:
Logical Shift Right by 30 positions (equivalent to Rotate Right by 2 positions):
Bitwise OR of X1 and X3:
Result stored in X1: 0x2E (46 in decimal)
1. Practicle Example: data_processing_instructions.s
2. Compilation and Debugging Setup
Compile and link:
Start gdbserver:
Connect with GDB:
3. Detailed Explanation of Each Instruction
mov x0, #10
andmov x1, #3
These instructions load immediate values into registers.
x0 = 10 (binary: 1010), x1 = 3 (binary: 0011)
add x2, x0, x1
Adds the values in x0 and x1, storing the result in x2.
Expected result: x2 = 13 (10 + 3)
sub x3, x0, x1
Subtracts x1 from x0, storing the result in x3.
Expected result: x3 = 7 (10 - 3)
mul x4, x0, x1
Multiplies x0 by x1, storing the result in x4.
Expected result: x4 = 30 (10 * 3)
udiv x5, x0, x1
Performs unsigned division of x0 by x1, storing the result in x5.
Expected result: x5 = 3 (10 / 3, integer division)
and x6, x0, x1
Performs bitwise AND between x0 and x1.
1010 (x0) AND 0011 (x1) = 0010
Expected result: x6 = 2
orr x7, x0, x1
Performs bitwise OR between x0 and x1.
1010 (x0) OR 0011 (x1) = 1011
Expected result: x7 = 11
eor x8, x0, x1
Performs bitwise XOR between x0 and x1.
1010 (x0) XOR 0011 (x1) = 1001
Expected result: x8 = 9
lsl x9, x0, #2
Logically shifts x0 left by 2 bits.
1010 becomes 101000
Expected result: x9 = 40 (10 * 2^2)
lsr x10, x0, #1
Logically shifts x0 right by 1 bit.
1010 becomes 0101
Expected result: x10 = 5 (10 / 2)
asr x11, x0, #1
Arithmetically shifts x0 right by 1 bit.
For positive numbers, same as LSR.
Expected result: x11 = 5
ror x12, x0, #2
Rotates x0 right by 2 bits.
1010 becomes 1010...10 (64-bit rotation)
Expected result: x12 = 1073741826 (2^30 + 2)
cmp x0, x1
andcset x13, gt
Compares x0 and x1, then sets x13 to 1 if x0 > x1, else 0.
Expected result: x13 = 1 (because 10 > 3)
4. Debugging Process
Step through each instruction:
Repeat for each instruction, observing how register values change after each operation.
3.3 System Instructions
System Instructions are special commands that allow a program to interact directly with the processor at a system level. These instructions are essential for:
Operating system operations
Hardware management
Maintaining system integrity
They are like the backstage commands that keep everything running smoothly in a computer system.
3.3.1 Exception Generation
Exception generation instructions intentionally cause the processor to enter an "exception state." This is useful for:
System calls (requests to the operating system)
Debugging
Handling errors
SVC (Supervisor Call)
Purpose: To make system calls (requests to the operating system).
Syntax:
svc #immediate
Example:
Explanation: When this instruction is executed, it causes the processor to switch to a more privileged execution mode. This allows the operating system to perform tasks that normal user programs cannot do directly, such as accessing hardware or performing critical system functions.
Practical Example:
Imagine you are writing a program that needs to read a file from disk. Reading files directly from the disk is a sensitive operation that requires special privileges. By using the svc #0
instruction, your program requests the operating system to handle the file reading process securely.
BRK (Breakpoint)
Purpose: To enter a debugging state.
Syntax:
brk #immediate
Example:
Explanation: This instruction pauses program execution and enters a debugger if one is attached. It's like setting a breakpoint in your code, which is a common debugging technique to inspect the state of the program at specific points.
Practical Example:
If you're developing a complex application and want to check the value of variables at a certain point, you can use the brk
instruction. When the program execution reaches the brk
instruction, it will pause, allowing you to inspect the variables' values.
HVC (Hypervisor Call)
Purpose: To call hypervisor functions in virtualized environments.
Syntax:
hvc #immediate
Example:
Explanation: In systems where multiple operating systems run on the same hardware (virtualization), this instruction allows a guest operating system to request services from the hypervisor, which manages the virtual machines.
In a cloud computing environment, multiple virtual machines (VMs) might run on a single physical server. If a VM needs to perform an operation that requires coordination with the hypervisor (like allocating more memory), it uses the hvc
instruction to request the hypervisor's assistance.
3.3.2 System Control
System control instructions manage the processor state and system registers, which are special storage locations used to control various aspects of the processor's operation.
MSR (Move to System Register)
Purpose: To write a value to a system register.
Syntax:
msr <system_register>, <source_register>
Example:
Explanation: This instruction writes the value in register
x0
to the system control registersctlr_el1
, which is used to control the behavior of the processor at Exception Level 1.
Suppose you need to change the configuration of the CPU's memory management. By writing a specific value to the sctlr_el1
register, you can enable or disable certain memory features.
MRS (Move from System Register)
Purpose: To read a value from a system register.
Syntax:
mrs <destination_register>, <system_register>
Example:
Explanation: This instruction reads the value from the system control register
sctlr_el1
and stores it in registerx0
.
If you want to check the current configuration of the CPU's memory management, you can read the value from the sctlr_el1
register into a general-purpose register like x0
to examine its settings.
3.3.3 Cache Maintenance
Cache maintenance instructions manage the processor's cache, which is a small, fast memory used to speed up access to frequently used data.
DC (Data Cache operation)
Purpose: To perform operations on the data cache.
Common Variants:
dc cvac
: Clean data cache by virtual address (writes back data from the cache to main memory).dc ivac
: Invalidate data cache by virtual address (marks data in the cache as invalid).
Example:
Explanation: This instruction cleans the cache line containing the address in
x0
, meaning it writes the data back to main memory and ensures consistency.
Practical Example:
When you modify data in memory, the changes are first made in the cache for speed. To ensure that the changes are saved to the main memory, you can use the dc cvac
instruction. This is important for data integrity, especially in multi-threaded applications where multiple processes might access the same data.
IC (Instruction Cache operation)
Purpose: To perform operations on the instruction cache.
Example:
Explanation: This instruction invalidates all entries in the instruction cache, meaning it marks them as outdated so that new instructions must be fetched from memory.
Practical Example:
After updating the code in memory (e.g., loading a new program or self-modifying code), the instruction cache may still hold old instructions. Using ic iallu
ensures that the CPU fetches the updated instructions from memory, preventing the execution of outdated code.
3.3.4 TLB (Translation Lookaside Buffer) Maintenance
The TLB is a special cache that speeds up the translation of virtual addresses to physical addresses.
TLBI (TLB Invalidate)
Purpose: To invalidate entries in the TLB.
Example:
Explanation: This instruction invalidates all TLB entries for the current virtual machine at Exception Level 1, forcing the processor to update its address mappings.
When the virtual-to-physical address mappings change (e.g., when a new program is loaded or the memory layout changes), the TLB needs to be updated. Using tlbi vmalle1is
ensures that the processor invalidates outdated mappings and fetches the new ones.
3.4 Branching and Condition Codes
3.4.1 Condition Codes
Condition codes are like little flags that our computer uses to remember the result of certain operations. They help us make decisions in our programs. In ARM64, there are four main condition codes:
N (Negative): Indicates if the result of the operation is negative.
Z (Zero): Indicates if the result of the operation is zero.
C (Carry): Indicates if there's a carry out of the most significant bit (useful for unsigned operations).
V (Overflow): Indicates if the operation resulted in an overflow (useful for signed operations).
These flags are stored in the PSTATE (Processor State) register.
How Do We Set These Flags?
We set these flags using special versions of normal instructions. These versions have an 's' at the end. For example:
We can also set flags using the compare instruction:
A Simple Example
Let's look at a basic example to understand how these flags are set:
File: condition_flags.s
Explanation:
Initialize registers: We set
x0
to 5 andx1
to 3.Perform subtraction and set flags: The
subs
instruction subtractsx1
fromx0
, stores the result inx2
, and sets the condition flags based on the result.Infinite loop: The
b .
instruction creates an infinite loop, causing the program to repeatedly branch to itself. This halts execution so we can inspect the state of the registers and flags in GDB.
Checking Flags in GDB
To see the condition flags in action, we can use GDB:
Assemble and Link the Program:
Start GDB Server:
Start GDB and Connect to the Server: Open a new terminal and start GDB:
Load the Program in GDB:
Connect to the Remote Target:
Step Through the Program:
Check the condition flags in the
cpsr
register.
Check CPSR Register:
This should show something like:
The CPSR register in GDB will show the condition flags. The condition flags are represented by specific bits in the CPSR register:
N: Bit 31
Z: Bit 30
C: Bit 29
V: Bit 28
For example, if the CPSR value is 0x20201000
, you can interpret the flags as follows:
N (Negative): Bit 31 = 0 (not set)
Z (Zero): Bit 30 = 0 (not set)
C (Carry): Bit 29 = 1 (set)
V (Overflow): Bit 28 = 0 (not set)
Understanding CPSR
The CPSR (Current Program Status Register) contains the condition flags as part of its bits. You can view the CPSR value in GDB and decode the flags from it.
Example:
Check CPSR Register Value:
Binary Representation: Convert the CPSR value to its binary form. For example,
0x20201000
in binary is0010 0000 0010 0000 0001 0000 0000 0000
.Extract Condition Flags:
N (Negative): Bit 31 = 0 (not set)
Z (Zero): Bit 30 = 0 (not set)
C (Carry): Bit 29 = 1 (set)
V (Overflow): Bit 28 = 0 (not set)
3.4.2 Branching
Branching is a fundamental concept in programming that allows the flow of execution to change based on certain conditions. In ARM64 assembly, branching is crucial for implementing control structures like if-else statements, loops, and switch cases. Branching is like making a decision in your code. It's how we tell the computer to do different things based on certain conditions.
Think of it like a fork in a road:
If it's sunny, go to the beach.
If it's raining, stay home.
In assembly, we use branches to create these decision points.
In ARM64, branching instructions are used to jump to different parts of the program. The main types of branching instructions are:
Unconditional Branch: Always jumps to the specified label.
Conditional Branch: Jumps to the specified label only if certain conditions are met.
1. Unconditional Branch
An unconditional branch always jumps to the specified label, regardless of any condition flags. It is used to transfer control unconditionally to another part of the program.
Example:
Explanation:
b target_label
is an unconditional branch. The program always jumps totarget_label
.The instruction
mov x0, #2
will not execute because the branch instructionb target_label
is executed first.
2. Common Conditional Branches:
1. B.eq (branch if equal)
Explanation:
B.eq: Jumps to the specified label if the Zero (Z) flag is set.
The Zero (Z) flag is set when the result of a comparison is zero, meaning the operands are equal.
Example:
Detailed Explanation:
mov x0, #5 and mov x1, #5:
Set
x0
to 5 andx1
to 5.Registers:
x0 = 5
,x1 = 5
cmp x0, x1:
Compares
x0
andx1
. Sincex0
equalsx1
, the Zero (Z) flag is set.Registers:
x0 = 5
,x1 = 5
Flags:
Z = 1
b.eq equal:
Branches to the
equal
label if the Zero (Z) flag is set.Since the Z flag is set, the program jumps to the
equal
label.
equal:
The branch is taken, so
x2
is set to 1, indicatingx0
equalsx1
.Registers:
x2 = 1
end:
The program reaches the
end
label and enters an infinite loop, stopping execution.The program does not execute any further instructions.
2. B.ne (branch if not equal)
Explanation:
B.ne: Jumps to the specified label if the Zero (Z) flag is not set.
The Zero (Z) flag is not set when the result of a comparison is not zero, meaning the operands are not equal.
Example:
Detailed Explanation:
mov x0, #5 and mov x1, #3:
Set
x0
to 5 andx1
to 3.Registers:
x0 = 5
,x1 = 3
cmp x0, x1:
Compares
x0
andx1
. Sincex0
does not equalx1
, the Zero (Z) flag is not set.Registers:
x0 = 5
,x1 = 3
Flags:
Z = 0
b.ne not_equal:
Branches to the
not_equal
label if the Zero (Z) flag is not set.Since the Z flag is not set, the program jumps to the
not_equal
label.
not_equal:
The branch is taken, so
x2
is set to 1, indicatingx0
does not equalx1
.Registers:
x2 = 1
end:
The program reaches the
end
label and enters an infinite loop, stopping execution.The program does not execute any further instructions.
3. B.lt (branch if less than)
Explanation:
B.lt: Jumps to the specified label if the Negative (N) flag is not equal to the Overflow (V) flag.
This indicates that the first operand is less than the second operand in signed comparison.
Example:
Detailed Explanation:
mov x0, #3 and mov x1, #5:
Set
x0
to 3 andx1
to 5.Registers:
x0 = 3
,x1 = 5
cmp x0, x1:
Compares
x0
andx1
. Sincex0
is less thanx1
, the Negative (N) flag is set.Registers:
x0 = 3
,x1 = 5
Flags:
N = 1
,V = 0
b.lt less_than:
Branches to the
less_than
label if the Negative (N) flag is not equal to the Overflow (V) flag.Since N is not equal to V, the program jumps to the
less_than
label.
less_than:
The branch is taken, so
x2
is set to 1, indicatingx0
is less thanx1
.Registers:
x2 = 1
end:
The program reaches the
end
label and enters an infinite loop, stopping execution.The program does not execute any further instructions.
4. B.le (branch if less than or equal)
Explanation:
B.le: Jumps to the specified label if the Zero (Z) flag is set or the Negative (N) flag is not equal to the Overflow (V) flag.
This indicates that the first operand is less than or equal to the second operand in signed comparison.
Example:
Detailed Explanation:
mov x0, #3 and mov x1, #5:
Set
x0
to 3 andx1
to 5.Registers:
x0 = 3
,x1 = 5
cmp x0, x1:
Compares
x0
andx1
. Sincex0
is less thanx1
, the Negative (N) flag is set.Registers:
x0 = 3
,x1 = 5
Flags:
N = 1
,V = 0
b.le less_or_equal:
Branches to the
less_or_equal
label if the Zero (Z) flag is set or the Negative (N) flag is not equal to the Overflow (V) flag.Since N is not equal to V, the program jumps to
the less_or_equal
label. 4. less_or_equal: - The branch is taken, so x2
is set to 1, indicating x0
is less than or equal to x1
. - Registers: x2 = 1
5. end: - The program reaches the end
label and enters an infinite loop, stopping execution. - The program does not execute any further instructions.
5. B.gt (branch if greater than)
Explanation:
B.gt: Jumps to the specified label if the Zero (Z) flag is not set and the Negative (N) flag is equal to the Overflow (V) flag.
This indicates that the first operand is greater than the second operand in signed comparison.
Example:
Detailed Explanation:
mov x0, #5 and mov x1, #3:
Set
x0
to 5 andx1
to 3.Registers:
x0 = 5
,x1 = 3
cmp x0, x1:
Compares
x0
andx1
. Sincex0
is greater thanx1
, the Zero (Z) flag is not set and the Negative (N) flag is equal to the Overflow (V) flag.Registers:
x0 = 5
,x1 = 3
Flags:
Z = 0
,N = 0
,V = 0
b.gt greater_than:
Branches to the
greater_than
label if the Zero (Z) flag is not set and the Negative (N) flag is equal to the Overflow (V) flag.Since Z is 0 and N is equal to V, the program jumps to the
greater_than
label.
greater_than:
The branch is taken, so
x2
is set to 1, indicatingx0
is greater thanx1
.Registers:
x2 = 1
end:
The program reaches the
end
label and enters an infinite loop, stopping execution.The program does not execute any further instructions.
6. B.ge (branch if greater than or equal)
Explanation:
B.ge: Jumps to the specified label if the Negative (N) flag is equal to the Overflow (V) flag.
This indicates that the first operand is greater than or equal to the second operand in signed comparison.
Example:
Detailed Explanation:
mov x0, #5 and mov x1, #3:
Set
x0
to 5 andx1
to 3.Registers:
x0 = 5
,x1 = 3
cmp x0, x1:
Compares
x0
andx1
. Sincex0
is greater thanx1
, the Negative (N) flag is equal to the Overflow (V) flag.Registers:
x0 = 5
,x1 = 3
Flags:
N = 0
,V = 0
b.ge greater_or_equal:
Branches to the
greater_or_equal
label if the Negative (N) flag is equal to the Overflow (V) flag.Since N is equal to V, the program jumps to the
greater_or_equal
label.
greater_or_equal:
The branch is taken, so
x2
is set to 1, indicatingx0
is greater than or equal tox1
.Registers:
x2 = 1
end:
The program reaches the
end
label and enters an infinite loop, stopping execution.The program does not execute any further instructions.
Example Program: branching_example.s
branching_example.s
Steps to Compile, Run, and Debug
Save the program: Save the above code to a file named
branching_example.s
.Assemble the program:
Link the program:
Start GDB Server:
Start GDB and Connect to the Server: Open a new terminal and start GDB:
Load the Program in GDB:
Connect to the Remote Target:
Step-by-Step Debugging with Explanations
Initial Setup:
Registers:
x0 = 5
Setting x1:
Registers:
x1 = 5
Compare x0 and x1:
Explanation: Compares
x0
andx1
. Sincex0
equalsx1
, the Zero (Z) flag is set.Registers:
x0 = 5
,x1 = 5
Flags:
Z = 1
Branch if Equal:
Explanation: Branches to the
equal
label if the Zero (Z) flag is set.Since the Z flag is set (Z = 1), the program jumps to the
equal
label.
Setting x2 at the
equal
label:Explanation: The branch is taken, so
x2
is set to 1, indicatingx0
equalsx1
.Registers:
x2 = 1
Modify x0 and x1 for less than comparison:
Registers:
x0 = 3
,x1 = 5
Compare x0 and x1 for less than:
Explanation: Compares
x0
andx1
. Sincex0
is less thanx1
, the Negative (N) flag is set.Registers:
x0 = 3
,x1 = 5
Flags:
N = 1
,V = 0
Branch if Less Than:
Explanation: Branches to the
less_than
label if the Negative (N) flag is set.Since N is set, the program jumps to the
less_than
label.
Setting x3 at the
less_than
label:Explanation: The branch is taken, so
x3
is set to 1, indicatingx0
is less thanx1
.Registers:
x3 = 1
Modify x0 and x1 for greater than comparison:
Registers:
x0 = 10
,x1 = 5
Compare x0 and x1 for greater than:
Explanation: Compares
x0
andx1
. Sincex0
is greater thanx1
, the Zero (Z) flag is not set and the Negative (N) flag is clear.Registers:
x0 = 10
,x1 = 5
Flags:
Z = 0
,N = 0
,V = 0
Branch if Greater Than:
Explanation: Branches to the
greater_than
label if the Zero (Z) flag is not set and the Negative (N) flag is equal to the Overflow (V) flag.Since Z is 0 and N is equal to V, the program jumps to the
greater_than
label.
Setting x4 at the
greater_than
label:Explanation: The branch is taken, so
x4
is set to 1, indicatingx0
is greater thanx1
.Registers:
x4 = 1
End and Infinite Loop:
Summary of the Program Execution:
Initial Comparison:
x0 = 5
,x1 = 5
`cmp x0, x
1sets
Z = 1 - Branches to
label_equal, sets
x2 = 1`
Less Than Comparison:
x0 = 3
,x1 = 5
cmp x0, x1
setsN = 1
Branches to
label_less_than
, setsx3 = 1
Greater Than Comparison:
x0 = 10
,x1 = 5
cmp x0, x1
setsZ = 0
,N = 0
,V = 0
Branches to
label_greater_than
, setsx4 = 1
End:
The program reaches the
end
label and enters an infinite loop.
Last updated