Let's start with the linker script Linker scripts have some prerequisite knowledge 1. Combine from multiple source files into one output file 2. Each object file has its own defined section list (ie 1. text section 2. data section ...) ### linker script We need to manually specify the location of each section. ```c= SECTIONS { . = 0x80000; .text : { *(.text) } } ``` Since the architecture is aarch64, the default load address is 0x80000. As you can see, our kernel is very simple, with only one text section (ie assembly file) So ".text" is defined, and the location must be appended to 0x80000 ### asm file ```c= .section ".text" .global _start _start: wfe b _start ``` This is a simple assembly code that defines "_start" as a global. ![](https://i.imgur.com/eDeTHAJ.png) So the type of _start is bound to GLOBAL. This is important because we need this symbol to find which part of the code will be the first instruction At this point, we have completed the above files, and now we can compile them and start it in the qemu system. ```shell= qemu-system-aarch64 -M raspi3 -kernel kernel8.img -display none -serial null -serial stdio -S -s ``` We started a simple kernel through the qemu system, But how to check the running status? Yes, GDB is here ```shell= $ gdb $ (gdb) target remote :1234 ``` As you can see, the process is attached. ![](https://i.imgur.com/4VQ8uRC.png) Well, look at the instructions and you will know that the code is the same as our asm file. The address also starts with 0x80000, because our linker script defines the location counter as 0x80000, and the text section follows the counter. --- @ arm platform series - 1 ###### tags: `CY`