├── first_program ├── first.s └── README.md ├── setting_up_qemu_for_arm ├── ls.png ├── pi.png ├── kernal.png ├── raspberry.png └── README.md ├── hardware_interactions ├── switchled.png ├── hardware_interactions.s └── README.md ├── conditional_instruction_execution ├── conditional_instruction_execution.s └── README.md ├── addressing_modes ├── addressing_mode.s └── README.md ├── logical_shifts_and_rotations ├── logical_shifts_and_rotations.s └── README.md ├── branch_with_link_register_and_returns ├── branch_with_link_register_and_returns.s └── README.md ├── arithmetic_and_cpsr_flags ├── arithmetic_and_cpsr_flags.s └── README.md ├── conditions_and_branches ├── conditions_and_branches.s └── README.md ├── logical_operations ├── logical_operations.s └── README.md ├── printing_strings_to_terminal ├── helloworld.s └── README.md ├── preserving_and_retrieving_data_from_stack_memory ├── preserving_and_retrieving_data_from_stack_memory.s └── README.md ├── loops_with_branches ├── loops_with_branches.s └── README.md ├── LICENSE ├── debugging_arm_programs_with_gdb └── README.md └── README.md /first_program/first.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0,#30 4 | 5 | MOV R7,#1 6 | SWI 0 -------------------------------------------------------------------------------- /setting_up_qemu_for_arm/ls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shikha-code36/assembly-ARM-tutorial/HEAD/setting_up_qemu_for_arm/ls.png -------------------------------------------------------------------------------- /setting_up_qemu_for_arm/pi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shikha-code36/assembly-ARM-tutorial/HEAD/setting_up_qemu_for_arm/pi.png -------------------------------------------------------------------------------- /hardware_interactions/switchled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shikha-code36/assembly-ARM-tutorial/HEAD/hardware_interactions/switchled.png -------------------------------------------------------------------------------- /setting_up_qemu_for_arm/kernal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shikha-code36/assembly-ARM-tutorial/HEAD/setting_up_qemu_for_arm/kernal.png -------------------------------------------------------------------------------- /setting_up_qemu_for_arm/raspberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Shikha-code36/assembly-ARM-tutorial/HEAD/setting_up_qemu_for_arm/raspberry.png -------------------------------------------------------------------------------- /conditional_instruction_execution/conditional_instruction_execution.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | 4 | MOV R0,#2 5 | MOV R1,#4 6 | CMP R0,R1 7 | 8 | ADDLT R2,#1 9 | MOVGE R2,#5 -------------------------------------------------------------------------------- /addressing_modes/addressing_mode.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | LDR R0,=list 4 | LDR R1, [R0] 5 | LDR R2,[R0,#4]! 6 | LDR R2,[R0],#4 7 | 8 | .data 9 | list: 10 | .word 4,5,-9,1,0,2,-3 11 | -------------------------------------------------------------------------------- /logical_shifts_and_rotations/logical_shifts_and_rotations.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0, #15 4 | LSL R0, #1 5 | LSR R0, #1 6 | 7 | MOV R1,R0,LSL #1 8 | 9 | ROR R0,#1 10 | 11 | -------------------------------------------------------------------------------- /hardware_interactions/hardware_interactions.s: -------------------------------------------------------------------------------- 1 | .equ SWITCH, 0xff200040 2 | .equ LED, 0xff200000 3 | 4 | .global _start 5 | _start: 6 | LDR R0,=SWITCH 7 | LDR R1,[R0] 8 | 9 | LDR R0,=LED 10 | STR R1,[R0] -------------------------------------------------------------------------------- /branch_with_link_register_and_returns/branch_with_link_register_and_returns.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | 4 | MOV R0,#1 5 | MOV R1,#3 6 | BL add2 7 | MOV R3,#4 8 | 9 | add2: 10 | ADD R2,R0,R1 11 | bx lr -------------------------------------------------------------------------------- /arithmetic_and_cpsr_flags/arithmetic_and_cpsr_flags.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0, #5 4 | MOV R1, #7 5 | ADD R2,R0,R1 6 | SUB R2,R0,R1 7 | MUL R2,R0,R1 8 | 9 | SUBS R2,R0,R1 10 | ADDS R2,R0,R1 11 | ADC R2,R0,R1 -------------------------------------------------------------------------------- /conditions_and_branches/conditions_and_branches.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0,#3 4 | MOV R1,#2 5 | 6 | CMP R0,R1 7 | 8 | BGT greater 9 | BAL default 10 | 11 | greater: 12 | MOV R2,#1 13 | 14 | default: 15 | MOV R2,#2 16 | 17 | -------------------------------------------------------------------------------- /logical_operations/logical_operations.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0,#0xFF 4 | MOV R1,#22 5 | AND R2,R0,R1 6 | ANDS R2,R0,R1 7 | ORR R2,R0,R1 8 | EOR R2,R0,R1 9 | 10 | MOV R0,#0xFF 11 | MVN R0,R0 12 | AND R0,R0,#0x000000FF 13 | 14 | -------------------------------------------------------------------------------- /printing_strings_to_terminal/helloworld.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0,#1 4 | LDR R1,=message 5 | LDR R2,=len 6 | MOV R7,#4 7 | SWI 0 8 | 9 | MOV R7,#1 10 | SWI 0 11 | 12 | .data 13 | message: 14 | .asciz "radhe radhe \n" 15 | len = .-message -------------------------------------------------------------------------------- /preserving_and_retrieving_data_from_stack_memory/preserving_and_retrieving_data_from_stack_memory.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | MOV R0,#1 4 | MOV R1,#3 5 | PUSH {R0,R1} 6 | BL get_value 7 | POP {R0,R1} 8 | B end 9 | 10 | get_value: 11 | MOV R0,#5 12 | MOV R1,#7 13 | ADD R2,R0,R1 14 | BX lr 15 | 16 | end: -------------------------------------------------------------------------------- /loops_with_branches/loops_with_branches.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | .equ endlist, 0xaaaaaaaa 3 | 4 | _start: 5 | LDR R0,=list 6 | LDR R3,=endlist 7 | LDR R1,[R0] 8 | ADD R2,R2,R1 9 | 10 | loop: 11 | LDR R1,[R0,#4]! 12 | CMP R1,R3 13 | BEQ exit 14 | ADD R2,R2,R1 15 | BAL loop 16 | 17 | exit: 18 | 19 | .data 20 | list: 21 | .word 1,2,3,4,5,6,7,8,9,10 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Shikha Pandey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /first_program/README.md: -------------------------------------------------------------------------------- 1 | ## ARM Assembly Code Explanation 2 | 3 | The given code snippet is an ARM assembly language program that performs a simple system call to exit a program. Here's a line-by-line breakdown: 4 | 5 | - `.global _start`: This line declares `_start` as a global label, which means it can be seen by other files and is typically used as the entry point of the program. 6 | 7 | - `_start:`: This is the label for the entry point of the program. 8 | 9 | - `MOV R0,#30`: This instruction moves the literal value `30` into register `R0`. In this context, it's just loading data into `R0`, but it's not used further in this program. 10 | 11 | - `MOV R7,#1`: This instruction moves the literal value `1` into register `R7`. The value `1` is a special number that represents the system call number for exiting a program. 12 | 13 | - `SWI 0`: This instruction triggers a software interrupt with value `0`. The software interrupt (`SWI`) is used to make a system call in ARM. The operating system checks register `R7` to determine which system call to execute. Since we've moved `1` into `R7`, it corresponds to the exit system call. 14 | 15 | The narrative provided explains that register `R7` is used for system calls in ARM architecture. When an interrupt is called, the operating system looks at `R7` to determine what action to take based on the value it contains. In this case, since `R7` contains `1`, it tells the operating system to terminate the current program. 16 | -------------------------------------------------------------------------------- /conditional_instruction_execution/README.md: -------------------------------------------------------------------------------- 1 | # Conditional Instruction Execution in ARM Assembly 2 | 3 | This ARM assembly code snippet demonstrates the use of conditional execution of instructions. Below is a line-by-line explanation of the code and its flow: 4 | 5 | ## Code Snippet 6 | ``` 7 | .global _start 8 | _start: 9 | 10 | MOV R0,#2 11 | MOV R1,#4 12 | CMP R0,R1 13 | 14 | ADDLT R2,R2,#1 15 | MOVGE R2,R2,#5 16 | ``` 17 | 18 | ## Explanation 19 | 20 | - `.global _start`: This line declares `_start` as a global label, making it visible to the linker. It's the entry point of the program. 21 | 22 | - `_start:`: This is a label that marks the beginning of the code segment. 23 | 24 | - `MOV R0,#2`: Moves the literal value `2` into register `R0`. 25 | 26 | - `MOV R1,#4`: Moves the literal value `4` into register `R1`. 27 | 28 | - `CMP R0,R1`: Compares the values in `R0` and `R1`. This sets the condition flags based on whether the value in `R0` is less than, equal to, or greater than the value in `R1`. 29 | 30 | - `ADDLT R2,R2,#1`: If the result of the comparison is Less Than (LT), this instruction adds `1` to the value in `R2` and stores the result back in `R2`. This instruction is executed only if `R0` is less than `R1`. 31 | 32 | - `MOVGE R2,R2,#5`: If the result of the comparison is Greater than or Equal (GE), this instruction moves the literal value `5` into register `R2`. This instruction is executed only if `R0` is greater than or equal to `R1`. 33 | 34 | The conditional instructions (`ADDLT`, `MOVGE`) make use of condition codes set by the preceding `CMP` instruction to determine whether they should be executed. 35 | 36 | Conditional execution helps in reducing branch instructions and can lead to more efficient code by avoiding pipeline flushes due to branch mispredictions. 37 | -------------------------------------------------------------------------------- /conditions_and_branches/README.md: -------------------------------------------------------------------------------- 1 | # Conditions and Branches in ARM Assembly 2 | 3 | ## Introduction 4 | In ARM assembly, branching allows for altering the flow of execution based on conditional tests. These conditions are evaluated through flags set by previous instructions, typically comparison operations. 5 | 6 | ## Branching Instructions 7 | - **B**: Unconditional branch, jumps to the specified label. 8 | - **BEQ**: Branch if equal, jumps if the last comparison was equal. 9 | - **BNE**: Branch if not equal, jumps if the last comparison was not equal. 10 | - **BGT**: Branch if greater than, jumps if the last comparison showed greater than. 11 | - **BLT**: Branch if less than, jumps if the last comparison showed less than. 12 | - **BLE**: Branch if less than or equal to, jumps if the last comparison showed less than or equal. 13 | - **BAL**: Branch always, an unconditional jump (equivalent to B). 14 | 15 | ## Example Code Explanation 16 | ```assembly 17 | .global _start 18 | _start: 19 | MOV R0,#1 20 | MOV R1,#2 21 | 22 | CMP R0,R1 23 | 24 | BGT greater 25 | BAL default 26 | 27 | greater: 28 | MOV R2,#1 29 | 30 | default: 31 | MOV R2,#2 32 | ``` 33 | 34 | ### Line-by-Line Breakdown: 35 | 1. `MOV R0,#1`: Load the immediate value 1 into register R0. 36 | 2. `MOV R1,#2`: Load the immediate value 2 into register R1. 37 | 3. `CMP R0,R1`: Compare the values in registers R0 and R1. 38 | 4. `BGT greater`: If R0 is greater than R1, branch to the label 'greater'. 39 | 5. `BAL default`: Unconditionally branch to the label 'default'. 40 | 41 | ### Execution Flow: 42 | - The `CMP` instruction sets condition flags based on the comparison of `R0` and `R1`. 43 | - If `R0` is greater than `R1`, execution jumps to `greater`, setting `R2` to 1. 44 | - If not, it falls through to `default` due to the unconditional branch (`BAL`), setting `R2` to 2. 45 | 46 | In this example, since `R0` contains 1 and `R1` contains 2, the condition for `BGT` is not met. Therefore, execution proceeds to the 'default' label where `R2` is set to 2. 47 | -------------------------------------------------------------------------------- /addressing_modes/README.md: -------------------------------------------------------------------------------- 1 | ## Code Breakdown 2 | 3 | ### The `.data` Section 4 | 5 | ```assembly 6 | .data 7 | list: 8 | .word 4,5,-9,1,0,2,-3 9 | ``` 10 | 11 | - **.data**: This directive indicates that we're starting a section for defining data. 12 | - **list**: This is a label that acts as a pointer to the beginning of our data in memory. 13 | - **.word**: This directive defines a series of 32-bit values (words). In ARM, a word is 32 bits or 4 bytes. 14 | 15 | ### The `.global` Directive and `_start` Label 16 | 17 | ```assembly 18 | .global _start 19 | _start: 20 | ``` 21 | 22 | - **.global _start**: This line makes the `_start` label accessible from other files, which is useful when linking multiple files. 23 | - **_start**: This label marks the entry point of our program where execution begins. 24 | 25 | ### Loading Data with `LDR` Instruction 26 | 27 | ```assembly 28 | LDR R0,=list 29 | LDR R1, [R0] 30 | LDR R2,[R0,#4]! 31 | LDR R2,[R0],#4 32 | ``` 33 | 34 | - **LDR R0,=list**: Loads the address of `list` into register R0. 35 | - **LDR R1, [R0]**: Loads the first word from `list` into register R1 (which is `4`). 36 | - **LDR R2,[R0,#4]!**: Pre-increment load; increments R0 by 4 (to point to `5`) and loads that into R2. 37 | - **LDR R2,[R0],#4**: Post-increment load; loads the word at current R0 (which is `-9`) into R2 and then increments R0 by 4. 38 | 39 | ### Understanding Addressing Modes 40 | 41 | Addressing modes in ARM determine how the processor calculates the effective address of an operand: 42 | 43 | - **Pre-increment**: The register is incremented before it's used for addressing. For example: 44 | ```assembly 45 | LDR R2,[R0,#4]! 46 | ``` 47 | Here, `R0` is incremented first, then `list[R0]` is accessed. 48 | 49 | - **Post-increment**: The register is used for addressing and then incremented. For example: 50 | ```assembly 51 | LDR R2,[R0],#4 52 | ``` 53 | Here, `list[R0]` is accessed first, then `R0` is incremented. 54 | 55 | ## Conclusion 56 | 57 | Through this guide, you've learned about data declaration in `.data`, program entry with `.global _start`, loading data with `LDR`, and addressing modes. These are foundational concepts that will aid you as you delve deeper into ARM assembly programming. 58 | -------------------------------------------------------------------------------- /printing_strings_to_terminal/README.md: -------------------------------------------------------------------------------- 1 | # ARM Assembly Printing Strings to Terminal 2 | 3 | Welcome to your Raspberry Pi linux terminal. If you're here, you've successfully connected via SSH using `ssh pi@127.0.0.1 -p 5022`. If you're unsure about the setup process, please refer to the previous notes on setting up QEMU for ARM [here](https://github.com/Shikha-code36/assembly-ARM-tutorial/tree/main/setting_up_qemu_for_arm). 4 | 5 | ## Writing the Code 6 | 7 | Open the `helloworld.s` file in the nano editor: 8 | 9 | ```sh 10 | nano helloworld.s 11 | ``` 12 | 13 | Here's the `helloworld.s` ARM assembly code: 14 | 15 | ```assembly 16 | .global _start 17 | _start: 18 | MOV R0,#1 19 | LDR R1,=message 20 | LDR R2,=len 21 | MOV R7,#4 22 | SWI 0 23 | 24 | MOV R7,#1 25 | SWI 0 26 | 27 | .data 28 | message: 29 | .asciz "radhe radhe \n" 30 | len = .-message 31 | ``` 32 | 33 | ## Code Explanation 34 | 35 | - `.global _start`: Marks the `_start` label as global, making it visible to the linker. 36 | - `_start:`: The entry point of our program. 37 | - `MOV R0,#1`: Moves the value `1` into register `R0`, which is used for file descriptor (stdout). 38 | - `LDR R1,=message`: Loads the address of the `message` label into register `R1`. 39 | - `LDR R2,=len`: Loads the address of the `len` label into register `R2`. 40 | - `MOV R7,#4`: Moves the value `4` into register `R7`, which is the system call number for 'write'. 41 | - `SWI 0`: Triggers an interrupt to invoke a system call. 42 | - `.data`: Indicates that what follows is data (not code). 43 | - `message:`: A label marking where our message starts. 44 | - `.asciz "radhe radhe \n"`: Defines a null-terminated string. 45 | - `len = .-message`: Defines the length of our message. 46 | 47 | ## Compiling and Running 48 | 49 | Compile the assembly code into an object file: 50 | 51 | ```sh 52 | as helloworld.s -o helloworld.o 53 | ``` 54 | 55 | Link the object file to create an executable: 56 | 57 | ```sh 58 | ld helloworld.o -o helloworld 59 | ``` 60 | 61 | Verify that all files are present: 62 | 63 | ```sh 64 | ls 65 | ``` 66 | 67 | Run your executable: 68 | 69 | ```sh 70 | ./helloworld 71 | ``` 72 | 73 | You should see the output: 74 | 75 | ``` 76 | radhe radhe 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /setting_up_qemu_for_arm/README.md: -------------------------------------------------------------------------------- 1 | # Setting Up QEMU for ARM on Ubuntu 2 | 3 | This guide assumes you have ubuntu machine in my case I am using a virtual machine for the setup. 4 | 5 | ## Step 1: Download the Raspbian Image 6 | 7 | Go to the [Raspbian images page](http://downloads.raspberrypi.org/raspbian/images/raspbian-2017-04-10/) and download the appropriate zip file. 8 | 9 | ![Raspbian Image](https://github.com/Shikha-code36/assembly-ARM-tutorial/blob/main/setting_up_qemu_for_arm/raspberry.png) 10 | 11 | ## Step 2: Extract the Image 12 | 13 | Extract the downloaded zip file to obtain the `.img` file. 14 | 15 | ## Step 3: Download the Kernel 16 | 17 | Visit the [qemu-rpi-kernel repository](https://github.com/dhruvvyas90/qemu-rpi-kernel/blob/master/kernel-qemu-4.4.34-jessie) and download the `kernel-qemu-4.4.34-jessie` file. 18 | 19 | ![Kernal Image](https://github.com/Shikha-code36/assembly-ARM-tutorial/blob/main/setting_up_qemu_for_arm/kernal.png) 20 | 21 | ## Step 4: Verify Your Files 22 | 23 | Check all your files with the `ls` command in your terminal. 24 | 25 | ![File Image](https://github.com/Shikha-code36/assembly-ARM-tutorial/blob/main/setting_up_qemu_for_arm/ls.png) 26 | 27 | ## Step 5: Run QEMU with Raspbian 28 | 29 | Run the following command, making sure to replace `/Documents/qmu_vms/` with the path to where your files are located: 30 | 31 | ```bash 32 | qemu-system-arm -kernel /Documents/qmu_vms/kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda /Documents/qmu_vms/2017-04-10-raspbian-jessie.img -nic user,hostfwd=tcp::5022-:22 -no-reboot 33 | ``` 34 | 35 | *Note: Write your own path where necessary.* 36 | 37 | This will open a Raspbian QEMU window. 38 | 39 | ## Step 6: Start SSH Service in QEMU 40 | 41 | Open a terminal in QEMU and start the SSH service: 42 | 43 | ```bash 44 | sudo service ssh start 45 | ``` 46 | 47 | ![Pi Image](https://github.com/Shikha-code36/assembly-ARM-tutorial/blob/main/setting_up_qemu_for_arm/pi.png) 48 | 49 | ## Step 7: SSH into QEMU from Ubuntu Terminal 50 | 51 | Open a new tab in your Ubuntu terminal and connect via SSH: 52 | 53 | ```bash 54 | ssh pi@127.0.0.1 -p 5022 55 | ``` 56 | 57 | The default password is `raspberry`. 58 | 59 | You are now logged into your QEMU virtual machine. 60 | -------------------------------------------------------------------------------- /hardware_interactions/README.md: -------------------------------------------------------------------------------- 1 | # Hardware Interactions 2 | 3 | This README provides an explanation of a simple assembly program that demonstrates hardware interactions between switches and LEDs on a simulated device. 4 | 5 | ## Assembly Code Explanation 6 | 7 | The provided assembly code snippet performs direct memory access to interact with hardware components, specifically LEDs and switches. Here's a line-by-line breakdown: 8 | 9 | - `.equ SWITCH, 0xff200040`: This line sets up an alias named `SWITCH` for the memory address `0xff200040`, which corresponds to the switches in the simulator. 10 | - `.equ LED, 0xff200000`: Similarly, `LED` is set as an alias for the memory address `0xff200000`, representing the LEDs in the simulator. 11 | 12 | - `.global _start`: This directive indicates that `_start` is a global label, which is where program execution begins. 13 | 14 | - `_start:`: The entry point of the program. 15 | 16 | - `LDR R0,=SWITCH`: Load the address of `SWITCH` into register R0. 17 | - `LDR R1,[R0]`: Load the value from the address contained in R0 (the state of switches) into register R1. 18 | 19 | - `LDR R0,=LED`: Load the address of `LED` into register R0. 20 | - `STR R1,[R0]`: Store the value from register R1 into the address contained in R0 (which will update the state of LEDs). 21 | 22 | ## Hardware Flow 23 | 24 | When this code is executed: 25 | 1. The current state of switches (on/off) is read into register R1. 26 | 2. The same state is then written to LEDs, causing them to reflect the state of switches. 27 | 28 | In essence, flipping a switch will turn on/off its corresponding LED. 29 | 30 | ## Simulator Image Explanation 31 | 32 | ![Simulator Interface](https://github.com/Shikha-code36/assembly-ARM-tutorial/blob/main/hardware_interactions/switchled.png) 33 | 34 | The image shows a simulator interface divided into two sections: "LEDs" and "Switches". Each section has its own set of addresses that correspond to physical components on an actual device. 35 | 36 | - **LEDs**: The indicators are at address `0xff200000`. In this example, three LEDs are lit, indicating that their corresponding switches are turned on. 37 | - **Switches**: Located at address `0xff200040`, several switches are in the 'on' position as indicated by checkmarks. 38 | 39 | This visual representation helps understand how the code manipulates these components through memory-mapped I/O addresses. 40 | 41 | -------------------------------------------------------------------------------- /logical_shifts_and_rotations/README.md: -------------------------------------------------------------------------------- 1 | # Logical Shifts and Rotations 2 | 3 | ## Theory 4 | 5 | In ARM assembly, logical shifts and rotations are operations that allow you to manipulate the bits of a register value. 6 | 7 | ### LSL (Logical Shift Left) 8 | The `LSL` instruction shifts all bits in a specified register to the left by a certain number of positions. Bits that are shifted off the end are lost, and zeros are shifted in from the right. This operation effectively multiplies the register value by 2 for each shift position. 9 | 10 | ### LSR (Logical Shift Right) 11 | The `LSR` instruction shifts all bits in a specified register to the right by a certain number of positions. Bits that are shifted off the end are lost, and zeros are shifted in from the left. This operation effectively divides the register value by 2 for each shift position, rounding towards zero. 12 | 13 | ### ROR (Rotate Right) 14 | The `ROR` instruction rotates all bits in a specified register to the right by a certain number of positions. The bits that are rotated off the end are reintroduced on the left. This is different from `LSR` as it preserves all bits and simply changes their positions. 15 | 16 | ## Code Explanation 17 | 18 | ```assembly 19 | .global _start 20 | _start: 21 | MOV R0, #15 ; Load literal value 15 into R0. 22 | LSL R0, #1 ; Perform logical shift left on R0 by 1 position. 23 | LSR R0, #1 ; Perform logical shift right on R0 by 1 position. 24 | 25 | MOV R1, R0, LSL #1 ; Move the value of R0 shifted left by 1 into R1. 26 | 27 | ROR R0, #1 ; Rotate right R0 by 1 position. 28 | ``` 29 | 30 | ### Line-by-Line Explanation 31 | 32 | - `MOV R0, #15`: This instruction moves the literal value 15 into register R0. 33 | - `LSL R0, #1`: This instruction shifts all bits in R0 to the left by one position. The value in R0 becomes 30 (15 * 2). 34 | - `LSR R0, #1`: This instruction shifts all bits in R0 to the right by one position. The value in R0 becomes 15 (30 / 2). 35 | - `MOV R1, R0, LSL #1`: This instruction moves into R1 the value of R0 shifted left by one position. The value in R1 becomes 30. 36 | - `ROR R0, #1`: This instruction rotates all bits in R0 to the right by one position. If we consider that before this operation, R0 had a value of 15 (00001111 in binary), after rotation, it would be (10000111 in binary), which is 135. 37 | 38 | ## Output Explanation 39 | 40 | After executing the above lines of code: 41 | 42 | - The final value in **R0** is **135**, due to the rotate right operation. 43 | - The final value in **R1** is **30**, as it was moved from R0 after performing a logical shift left. 44 | 45 | -------------------------------------------------------------------------------- /branch_with_link_register_and_returns/README.md: -------------------------------------------------------------------------------- 1 | # Branch with Link Register and Returns in ARM 2 | 3 | ## Introduction 4 | In ARM assembly, branching is a fundamental concept that allows for the execution flow to jump from one part of the program to another. The `BL` (Branch with Link) instruction is particularly important as it not only branches to a subroutine but also stores the return address in the link register (LR), which is `R14`. This enables the subroutine to return to the point immediately after where it was called using `bx lr`. 5 | 6 | ## Code Explanation 7 | 8 | ```assembly 9 | .global _start 10 | _start: 11 | 12 | MOV R0,#1 ; Move immediate value 1 into register R0. 13 | MOV R1,#3 ; Move immediate value 3 into register R1. 14 | BL add2 ; Branch with link to subroutine 'add2' and store return address in LR. 15 | MOV R3,#4 ; Move immediate value 4 into register R3 (this line is executed after returning from 'add2'). 16 | 17 | add2: 18 | ADD R2,R0,R1 ; Add values in R0 and R1, store result in R2. 19 | bx lr ; Branch to address in link register, effectively returning to caller. 20 | ``` 21 | 22 | ### _start Label 23 | - The `_start` label marks the beginning of the program. This is where execution starts after loading the program. 24 | 25 | ### MOV Instructions 26 | - `MOV R0,#1` and `MOV R1,#3` are move instructions that load the registers `R0` and `R1` with immediate values `1` and `3`, respectively. 27 | 28 | ### BL Instruction 29 | - `BL add2` is a branch with link instruction. It performs two actions: 30 | - It branches execution to the label `add2`, which marks the beginning of a subroutine. 31 | - It stores the return address (the address of the instruction following `BL`, which is `MOV R3,#4`) into the link register (`LR` or `R14`). 32 | 33 | ### add2 Subroutine 34 | - The `add2` label marks a subroutine designed to add two numbers. 35 | - The `ADD R2,R0,R1` instruction adds the values of `R0` and `R1`, then stores the result in `R2`. 36 | - After performing its task, the subroutine uses `bx lr` to return to the caller. The `bx lr` instruction causes a branch to the address stored in the link register (`LR`). In this case, it returns to the instruction following the `BL add2`, which is `MOV R3,#4`. 37 | 38 | ### MOV Instruction After BL 39 | - The instruction `MOV R3,#4` is executed after returning from the subroutine. It moves an immediate value of `4` into register `R3`. 40 | 41 | ## Conclusion 42 | The use of the link register (`LR`) and branch with link (`BL`) instructions allows for efficient subroutine calls within ARM assembly programs. By storing the return address in a dedicated register, subroutines can perform their tasks and then return control back to the main program flow seamlessly. 43 | 44 | -------------------------------------------------------------------------------- /logical_operations/README.md: -------------------------------------------------------------------------------- 1 | # Logical Operations 2 | 3 | This code snippet is written in ARM assembly language and demonstrates the use of basic data processing instructions such as MOV, AND, ANDS, ORR, EOR, and MVN. 4 | 5 | ## Code Breakdown 6 | - `MOV R0,#0xFF`: This instruction moves the hexadecimal value 0xFF into register R0. 7 | - `MOV R1,#22`: Moves the decimal value 22 into register R1. 8 | - `AND R2,R0,R1`: Performs a bitwise AND operation between the values in R0 and R1, storing the result in R2. 9 | - `ANDS R2,R0,R1`: Similar to AND, but this instruction also updates the condition flags based on the result. 10 | - `ORR R2,R0,R1`: Performs a bitwise OR operation between R0 and R1, storing the result in R2. 11 | - `EOR R2,R0,R1`: Performs a bitwise Exclusive OR operation between R0 and R1, storing the result in R2. 12 | 13 | ## Using ANDS instead of AND 14 | The `ANDS` instruction is used instead of `AND` when we want to update the condition flags based on the result of the operation. Condition flags can affect subsequent instructions depending on their outcomes. 15 | 16 | ## Negation with MVN 17 | - `MVN R0,R0`: The MVN (Move Not) instruction performs bitwise negation (NOT) on the value in R0 and stores the result back into R0. 18 | 19 | ## Purpose of the Code Block 20 | The last three instructions: 21 | ``` 22 | MOV R0,#0xFF 23 | MVN R0,R0 24 | AND R0,R0,#0x000000FF 25 | ``` 26 | These lines set register R0 to 0xFF, then negate it (which would result in 0xFFFFFF00 on a 32-bit system), and finally perform an AND operation with 0x000000FF. The purpose here is to demonstrate negation and then isolate the lower 8 bits of the register by clearing out all other bits. 27 | 28 | ## Code Breakdown with Outputs 29 | - `MOV R0,#0xFF`: Moves the hexadecimal value 0xFF (255 in decimal) into register R0. 30 | - `MOV R1,#22`: Moves the decimal value 22 into register R1. 31 | 32 | Now, let's calculate the results of the bitwise operations: 33 | 34 | - `AND R2,R0,R1`: The binary representation of R0 (0xFF) is `11111111`, and R1 (22) is `00010110`. The AND operation will result in `00010110` (22 in decimal) being stored in R2 because only the bits that are set in both R0 and R1 remain set. 35 | 36 | - `ANDS R2,R0,R1`: This will produce the same result as the AND operation, `00010110` (22 in decimal), but it will also update the condition flags based on this result. For example, if the result is zero, the zero flag will be set. 37 | 38 | - `ORR R2,R0,R1`: The OR operation sets a bit in R2 if it is set in either R0 or R1. So, `11111111` OR `00010110` will result in `11111111` being stored in R2, which is 255 in decimal. 39 | 40 | - `EOR R2,R0,R1`: The Exclusive OR operation sets a bit in R2 if it is set in one operand but not both. So, `11111111` EOR `00010110` will result in `11101001` being stored in R2, which is 233 in decimal. 41 | 42 | For the negation part: 43 | - `MOV R0,#0xFF`: Sets R0 to 255 (`11111111`). 44 | - `MVN R0,R0`: Negates the value in R0. The negation of `11111111` is `00000000` on a 32-bit system since MVN flips all bits. 45 | - `AND R0,R0,#0x000000FF`: This AND operation won't change the value because it's essentially ANDing with itself. So, R0 remains as `00000000`. 46 | -------------------------------------------------------------------------------- /debugging_arm_programs_with_gdb/README.md: -------------------------------------------------------------------------------- 1 | # Debugging ARM Programs with GDB 2 | 3 | Welcome to the final chapter of our ARM assembly tutorial. In this section, we'll explore how to debug ARM programs using the GNU Debugger (GDB). We'll use our previous chapter's program as an example, which you can find [here](https://github.com/Shikha-code36/assembly-ARM-tutorial/tree/main/printing_strings_to_terminal). 4 | 5 | ## What is GDB? 6 | 7 | GDB, or the GNU Debugger, is a powerful tool used by developers to debug programs. It allows you to see what is going on 'inside' another program while it executes or what another program was doing at the moment it crashed. GDB can do four main kinds of things to help you catch bugs in the act: 8 | - Start your program, specifying anything that might affect its behavior. 9 | - Make your program stop on specified conditions. 10 | - Examine what has happened when your program has stopped. 11 | - Change things in your program so you can experiment with correcting the effects of one bug and go on to learn about another. 12 | 13 | ## Why Use GDB? 14 | 15 | GDB allows you to trace the execution of your code line by line, inspect memory and registers, change variable values at runtime, and even when your program crashes, it helps you to examine the state it was in. 16 | 17 | ## Debugging with GDB 18 | 19 | Let's walk through some common GDB commands using our `helloworld` program as an example: 20 | 21 | ### Starting GDB 22 | 23 | ```bash 24 | gdb helloworld 25 | ``` 26 | This command starts the debugger with `helloworld` loaded. 27 | 28 | ### Setting Breakpoints 29 | 30 | ```bash 31 | break _start 32 | ``` 33 | This sets a breakpoint at the beginning of the program (`_start` label). 34 | 35 | ### Running the Program 36 | 37 | ```bash 38 | run 39 | ``` 40 | Begins execution of your program up to the next breakpoint or until completion. 41 | 42 | ### Inspecting Registers 43 | 44 | ```bash 45 | (gdb) info register r0 46 | r0 0x0 0 47 | ``` 48 | Displays the current value of register `r0`. 49 | 50 | ### Stepping Through Instructions 51 | 52 | ```bash 53 | (gdb) stepi 54 | 0x00010078 in _start () 55 | (gdb) stepi 56 | 0x0001007c in _start () 57 | ``` 58 | Executes one instruction at a time. 59 | 60 | ### Examining Memory 61 | 62 | ```bash 63 | (gdb) x/10x $r1 64 | ``` 65 | Displays memory contents at the address contained in `r1` in hexadecimal format. 66 | 67 | ### Changing Layouts 68 | 69 | ```bash 70 | layout regs 71 | ``` 72 | Switches to a layout that displays registers. 73 | 74 | Here's an example showing how we can examine memory as characters: 75 | 76 | ```bash 77 | (gdb) x/15c $r1 78 | 0x20098: 114 'r' 97 'a' 100 'd' 104 'h' 101 'e' 32 ' ' 114 'r' 97 'a' 79 | 0x200a0: 100 'd' 104 'h' 101 'e' 32 ' ' 10 '\n' 0 '\000' 65 'A' 80 | ``` 81 | 82 | As you can see, we've printed "radhe radhe" followed by a newline and null terminator. 83 | 84 | ### Assembly Layout 85 | 86 | ```bash 87 | layout asm 88 | ``` 89 | Switches to a layout that displays disassembled code. 90 | 91 | 92 | 93 | ``` 94 | Thank you everyone for following along with this tutorial. We hope you've found it helpful in understanding ARM assembly and how to debug programs using GDB. Happy coding! 95 | ``` 96 | -------------------------------------------------------------------------------- /arithmetic_and_cpsr_flags/README.md: -------------------------------------------------------------------------------- 1 | # Arithmetic Operations and CPSR Flags in ARM Assembly 2 | 3 | ARM assembly language provides a set of instructions for performing arithmetic operations. These operations can also affect the Current Program Status Register (CPSR) flags, which are used for conditional execution of subsequent instructions. 4 | 5 | ## Basic Arithmetic Instructions 6 | 7 | Here's a breakdown of the basic arithmetic instructions used in ARM assembly: 8 | 9 | - `MOV`: This instruction moves a value into a register. For example: 10 | ```assembly 11 | MOV R0, #5 12 | ``` 13 | This line moves the literal value 5 into register R0. 14 | 15 | - `ADD`: This instruction adds two register values and stores the result in a register. For example: 16 | ```assembly 17 | ADD R2, R0, R1 18 | ``` 19 | This line adds the values in R0 and R1, then stores the result in R2 (R2 = R0 + R1). 20 | 21 | - `SUB`: This instruction subtracts one register value from another and stores the result. For example: 22 | ```assembly 23 | SUB R2, R0, R1 24 | ``` 25 | This line subtracts the value in R1 from R0 and stores the result in R2 (R2 = R0 - R1). 26 | 27 | - `MUL`: This instruction multiplies two register values and stores the result. For example: 28 | ```assembly 29 | MUL R2, R0, R1 30 | ``` 31 | This line multiplies the values in R0 and R1 and stores the result in R2 (R2 = R0 * R1). 32 | 33 | ## CPSR Flags and Suffix Instructions 34 | 35 | The CPSR flags are affected by certain arithmetic instructions that have an 'S' suffix (e.g., `ADDS`, `SUBS`). These flags include: 36 | 37 | - **N (Negative)**: Set if the result of an operation is negative. 38 | - **Z (Zero)**: Set if the result is zero. 39 | - **C (Carry)**: Set if there's a carry out or borrow during an operation. 40 | - **V (Overflow)**: Set if there's an overflow from signed operations. 41 | 42 | Here are some instructions that affect CPSR flags: 43 | 44 | - `SUBS`: Subtracts like `SUB` but also updates CPSR flags. It's useful for setting up conditions for subsequent instructions. 45 | ```assembly 46 | SUBS R2, R0, R1 47 | ``` 48 | This line not only subtracts the value in R1 from R0 but also updates the CPSR flags based on the result. 49 | 50 | - `ADDS`: This instruction adds two register values and updates the CPSR flags based on the result. For example: 51 | ```assembly 52 | ADDS R2, R0, R1 53 | ``` 54 | This line performs addition (R2 = R0 + R1) and sets the CPSR flags accordingly. If the result is zero, the Z flag is set. If there's a carry out, the C flag is set. 55 | 56 | - `ADC`: This instruction adds two register values along with the carry flag from a previous operation. For example: 57 | ```assembly 58 | ADC R2, R0, R1 59 | ``` 60 | This line adds the values in R0 and R1 plus the carry flag from CPSR (if it's set). It's useful when performing multi-word arithmetic operations. 61 | 62 | ## Conclusion 63 | 64 | Understanding these basic arithmetic instructions and how they interact with CPSR flags is crucial for writing effective ARM assembly code. These concepts allow for conditional execution based on previous operations, which is a powerful feature of ARM architecture. 65 | 66 | Apologies for missing those. Let's add explanations for `ADDS` and `ADC`: 67 | 68 | ## Extended Arithmetic Instructions with CPSR Flags 69 | 70 | These instructions are particularly useful for implementing complex arithmetic operations that depend on the results of previous calculations. 71 | 72 | I hope this completes your README.md content. Let me know if there's anything else you'd like to include! 73 | -------------------------------------------------------------------------------- /loops_with_branches/README.md: -------------------------------------------------------------------------------- 1 | # Loops with Branches 2 | 3 | This README.md provides a detailed explanation of an ARM assembly code snippet that demonstrates the use of loops with branches. The code calculates the sum of a list of numbers using a loop structure. 4 | 5 | ## Code Explanation 6 | 7 | ### Setup 8 | ```assembly 9 | .global _start 10 | .equ endlist, 0xaaaaaaaa 11 | ``` 12 | - `.global _start`: This line makes the `_start` label accessible from other files, which is necessary for the linker. 13 | - `.equ endlist, 0xaaaaaaaa`: This line defines a constant `endlist` with the value `0xaaaaaaaa`, which we'll use as a sentinel value to mark the end of our list. 14 | 15 | ### Entry Point 16 | ```assembly 17 | _start: 18 | LDR R0,=list 19 | LDR R3,=endlist 20 | LDR R1,[R0] 21 | ADD R2,R2,R1 22 | ``` 23 | - `_start:`: This label marks the entry point of our code. 24 | - `LDR R0,=list`: Loads the address of the `list` into register `R0`. 25 | - `LDR R3,=endlist`: Loads the sentinel value into register `R3`. 26 | - `LDR R1,[R0]`: Loads the first word (number) from the address pointed by `R0` into register `R1`. 27 | - `ADD R2,R2,R1`: Adds the value in `R1` to `R2`. Since `R2` is not initialized, it should be cleared before this operation to avoid undefined behavior. 28 | 29 | ### Loop Structure 30 | ```assembly 31 | loop: 32 | LDR R1,[R0,#4]! 33 | CMP R1,R3 34 | BEQ exit 35 | ADD R2,R2,R1 36 | BAL loop 37 | ``` 38 | - `loop:`: This label marks the beginning of our loop. 39 | - `LDR R1,[R0,#4]!`: Loads the next word from the address pointed by `R0` into `R1` and then increments `R0` by 4 bytes (since our list contains 32-bit numbers). 40 | - `CMP R1,R3`: Compares the loaded word in `R1` with our sentinel value in `R3`. 41 | - `BEQ exit`: If the values are equal (meaning we've hit our sentinel value), branch to the label `exit`. 42 | - `ADD R2,R2,R1`: If not equal, add the value in `R1` to our running total in `R2`. 43 | - `BAL loop`: Unconditionally branch back to the beginning of the loop to process the next number. 44 | 45 | ### Exit Point 46 | ```assembly 47 | exit: 48 | ``` 49 | - `exit:`: This label marks our exit point from the loop where we can proceed to further instructions or terminate the program. 50 | 51 | ### Data Section 52 | ```assembly 53 | .data 54 | list: 55 | .word 1,2,3,4,5,6,7,8,9,10 56 | ``` 57 | - `.data`: This directive indicates that we are starting a data section where we define our list. 58 | - `list:`: This label marks the beginning of our list in memory. 59 | - `.word 1,2,3,...`: Defines a series of 32-bit numbers that will be summed by our code. 60 | 61 | ## Flow and Register Values 62 | 63 | At each iteration of the loop: 64 | - **R0** holds the current address being read from our list. 65 | - **R1** holds the current number being added to our sum. 66 | - **R2** accumulates our running total sum. 67 | - **R3** always holds our sentinel value for comparison. 68 | 69 | Initially: 70 | - **R0** = address of first element in list (value = 1) 71 | - **R1** = first number from list (value = 1) 72 | - **R2** = undefined (should be initialized to 0 before starting) 73 | 74 | After first iteration: 75 | - **R0** = address of second element (value = 2) 76 | - **R1** = second number from list (value = 2) 77 | - **R2** = sum so far (value = 1) 78 | 79 | This pattern continues until **R1** equals **endlist**, at which point we exit the loop. 80 | 81 | Remember to initialize **R2** to zero before entering `_start`, as it's used for accumulating our sum. Also note that this code does not handle termination properly; it will just stop executing after reaching the end of the loop without any clean-up or system call to exit. 82 | -------------------------------------------------------------------------------- /preserving_and_retrieving_data_from_stack_memory/README.md: -------------------------------------------------------------------------------- 1 | # Preserving and Retrieving Data From Stack Memory 2 | 3 | In computer architecture, stack memory plays a crucial role in managing data during program execution, particularly when dealing with function calls and local variables. The stack is a special region of memory that operates on a Last In, First Out (LIFO) principle, meaning that the last piece of data placed onto the stack will be the first one to be removed. This feature is particularly useful for preserving the state of a program at a certain point, such as before calling a subroutine, and then retrieving it later. 4 | 5 | ## Subroutine in Assembly 6 | A subroutine is a sequence of program instructions that perform a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed. 7 | 8 | ## Assembly Code Explanation 9 | Below is an assembly code snippet that demonstrates how data can be preserved on the stack before calling a subroutine and how it can be retrieved afterward: 10 | 11 | ```assembly 12 | .global _start 13 | _start: 14 | MOV R0,#1 ; Move literal value 1 into register R0 15 | MOV R1,#3 ; Move literal value 3 into register R1 16 | PUSH {R0,R1} ; Push registers R0 and R1 onto the stack 17 | BL get_value ; Branch with link to subroutine 'get_value' 18 | POP {R0,R1} ; Pop values from the stack back into registers R0 and R1 19 | B end ; Branch to label 'end' 20 | 21 | get_value: 22 | MOV R0,#5 ; Move literal value 5 into register R0 (overwriting previous value) 23 | MOV R1,#7 ; Move literal value 7 into register R1 (overwriting previous value) 24 | ADD R2,R0,R1 ; Add values in R0 and R1, store result in R2 25 | BX lr ; Branch to address in link register (return from subroutine) 26 | 27 | end: 28 | ``` 29 | 30 | ### Line by Line Explanation: 31 | - `.global _start`: This directive makes the `_start` label globally accessible, marking it as an entry point for the program. 32 | - `_start:`: This label indicates where the program should start executing. 33 | - `MOV R0,#1`: Moves the literal value `1` into register `R0`. 34 | - `MOV R1,#3`: Moves the literal value `3` into register `R1`. 35 | - `PUSH {R0,R1}`: Pushes the contents of registers `R0` and `R1` onto the stack. This preserves their values before calling the subroutine. 36 | - `BL get_value`: The 'Branch with Link' instruction calls the subroutine `get_value`. It also stores the return address in the link register (`lr`). 37 | - `POP {R0,R1}`: Pops values off the stack back into registers `R0` and `R1`, retrieving their original values. 38 | - `B end`: Branches to label `end`, effectively ending the program. 39 | 40 | ### Subroutine Explanation: 41 | - `get_value:`: Label marking the start of the subroutine. 42 | - `MOV R0,#5`: Moves the literal value `5` into register `R0`. 43 | - `MOV R1,#7`: Moves the literal value `7` into register `R1`. 44 | - `ADD R2,R0,R1`: Adds values in registers `R0` and `R1`, storing the result in register `R2`. 45 | - `BX lr`: 'Branch and Exchange' instruction causes a branch to the address contained in the link register (`lr`), which returns control to the point after where the subroutine was called. 46 | 47 | ### Flow of Code: 48 | The flow starts at `_start`, where it initializes registers and preserves their values on the stack. It then calls a subroutine (`get_value`) that performs an addition operation. After returning from the subroutine, it retrieves the preserved values from the stack before ending execution at label 'end'. 49 | 50 | This simple example illustrates how data can be safely stored on and retrieved from stack memory across subroutine calls, ensuring that each function has access to its required data without interfering with other parts of a program. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Guide to ARM Assembly Language 2 | 3 | ## Introduction 4 | ARM assembly language is a low-level programming language designed for ARM (Advanced RISC Machine) processors, which are prevalent in embedded systems like smartphones and laptops. It enables direct interaction with the hardware, offering precise control over the device's operations. 5 | 6 | It is estimated that over 200 billion devices contain an ARM chip, making the arm language valuable to understand. By understanding the arm assembly language, programmers can work at a lower level, allowing them to write code that interacts with hardware in an efficient manner. Arm is a programming language that's used in a variety of different applications. You see it in a lot of different embedded devices. And really popular devices such as different phones, a lot of Android devices and some iPhone devices are running ARM based chips. 7 | 8 | ## Registers 9 | Registers are fast-access storage locations within the CPU that hold data temporarily during execution. They play a crucial role in assembly language programming due to their speed compared to memory access. 10 | 11 | ### General-Purpose Registers (R0-R6) 12 | - **R0-R6**: Used for general computations and temporary storage. 13 | - **Example**: Storing and adding numbers. 14 | ```assembly 15 | MOV R0, #5 ; Move 5 into R0 16 | MOV R1, #10 ; Move 10 into R1 17 | ADD R2, R0, R1; Add R0 and R1, result in R2 (R2 = 15) 18 | ``` 19 | 20 | ### Special-Purpose Registers 21 | - **R7**: System Call Register for OS services. 22 | ```assembly 23 | MOV R7, #1 ; System call number for program exit 24 | SWI 0 ; Invoke system call 25 | ``` 26 | - **SP (Stack Pointer)**: Points to the stack's top for managing function calls and local variables. 27 | ```assembly 28 | PUSH {R0} ; Push R0 onto the stack 29 | POP {R0} ; Pop from stack into R0 30 | ``` 31 | - **LR (Link Register)**: Holds the return address for functions. 32 | ```assembly 33 | BL function ; Call 'function', store return address in LR 34 | ``` 35 | - **PC (Program Counter)**: Points to the next instruction. 36 | ```assembly 37 | LDR PC, [R0] ; Load address into PC from R0 38 | ``` 39 | 40 | ### CPSR (Current Program Status Register) 41 | Stores flags indicating conditions after operations, like negative or zero results. It guides conditional execution based on these flags. 42 | 43 | **Example**: Using flags for conditional branching. 44 | ```assembly 45 | CMP R0, R1 ; Compare R0 and R1 46 | BEQ label ; If equal (Zero flag set), branch to 'label' 47 | ``` 48 | 49 | ## Memory Sizes 50 | - **Word**: Maximum data size for a register (32 bits on a 32-bit processor). 51 | - **Half-word**: Half of a word (16 bits). 52 | - **Byte**: Always 8 bits. 53 | 54 | ## Stack Memory 55 | A slower but larger capacity memory used for complex data like arrays. Managed using the stack pointer (SP). 56 | 57 | ## Detailed Register Usage Examples 58 | 59 | ### Using General-Purpose Registers 60 | ```assembly 61 | MOV R3, #15 ; Store 15 in R3 62 | MOV R4, #20 ; Store 20 in R4 63 | MUL R5, R3, R4; Multiply R3 by R4, result in R5 (R5 = 300) 64 | ``` 65 | 66 | ### Managing Function Calls with LR and SP 67 | ```assembly 68 | PUSH {LR} ; Save LR before function call 69 | BL some_func ; Call 'some_func', LR updated with return address 70 | POP {LR} ; Restore LR after function return 71 | ``` 72 | 73 | ### Conditional Execution with CPSR Flags 74 | ```assembly 75 | SUBS R6, R4, R3; Subtract R3 from R4, update flags based on result 76 | BMI negative ; Branch to 'negative' if result is negative (Negative flag set) 77 | ``` 78 | 79 | This guide provides an organized overview of ARM assembly language programming concepts.Beginners can use this as a foundation for further learning and practice in ARM assembly programming. 80 | 81 | 82 | ### File Extensions for ARM Assembly 83 | 84 | - **.s**: Use this extension for ARM assembly code files intended for the GNU Assembler (GAS), which is part of the GNU toolchain commonly used on Linux systems, including the Raspberry Pi. 85 | 86 | - **.asm**: This extension can also be used for assembly code files but is more commonly associated with Intel syntax and assemblers like NASM or MASM. For ARM assembly on Raspberry Pi, `.s` is the preferred extension when using GAS. 87 | 88 | ## Comprehensive ARM Assembly Programming Guide 89 | 90 | This section outlines the complete journey of learning ARM Assembly Language, from writing your first program to advanced hardware interactions and debugging techniques. 91 | 92 | - [x] [First Program](first_program) 93 | - [x] [Addressing Modes](addressing_modes) 94 | - [x] [Arithmetic and CPSR Flags](arithmetic_and_cpsr_flags) 95 | - [x] [Logical Operations](logical_operations) 96 | - [x] [Logical Shifts and Rotations](logical_shifts_and_rotations) 97 | - [x] [Conditions and Branches](conditions_and_branches) 98 | - [x] [Loops with Branches](loops_with_branches) 99 | - [x] [Conditional Instruction Execution](conditional_instruction_execution) 100 | - [x] [Branch with Link Register and Returns](branch_with_link_register_and_returns) 101 | - [x] [Preserving and Retrieving Data From Stack Memory](preserving_and_retrieving_data_from_stack_memory) 102 | - [x] [Hardware Interactions](hardware_interactions) 103 | - [x] [Setting Up QEMU for ARM](setting_up_qemu_for_arm) 104 | - [x] [Printing Strings to Terminal](printing_strings_to_terminal) 105 | - [x] [Debugging Arm Programs with Gdb](debugging_arm_programs_with_gdb) 106 | 107 | ## Acknowledgements 108 | 109 | This guide is based on the video tutorial by Scott Cosentino. You can watch the full tutorial [here](https://youtu.be/gfmRrPjnEw4?si=WZeq4fv6NHZRJnpT) and visit his channel [Olive Stem Learning](https://www.youtube.com/@olivestemlearning) for more educational content. 110 | 111 | A special thanks to Scott Cosentino for the comprehensive tutorial on ARM assembly language. 112 | 113 | ## Show Your Support 114 | 115 | If you found this guide helpful, please consider starring the repository to show your support. Your star helps increase visibility and encourages more learners to discover and benefit from these educational resources. 116 | 117 | ## License 118 | 119 | This project is released under the [MIT License](LICENSE). 120 | --------------------------------------------------------------------------------