最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

03-對(duì)part1-bootstrapping的搬運(yùn)和翻譯

2023-07-25 11:23 作者:Xdz-2333  | 我要投稿

原文放在文章末尾

非黑色字體,以及非黑體字的圖片說(shuō)明/圖片標(biāo)題為我自己添加

我們應(yīng)該如何編寫代碼?

????????我們通過(guò)寫代碼來(lái)告訴樹莓派做什么.你可能知道代碼最終會(huì)變成一串0和1(二進(jìn)制).然而你知道我們不用像這樣編寫代碼后應(yīng)該會(huì)很高興,不然我們很容易忘記正在發(fā)生什么.實(shí)際上,將人類可讀的語(yǔ)言轉(zhuǎn)化為0和1正是編譯器的工作之一.

????????想要開(kāi)始,我們就得了解兩種語(yǔ)言,匯編和C.C語(yǔ)言被大多數(shù)現(xiàn)代軟件開(kāi)發(fā)者所熟知的同時(shí),匯編語(yǔ)言卻只有少數(shù)人"說(shuō)".這是一種低級(jí)語(yǔ)言,它與CPU的"思維"方式非常相似,因此它給我們了許多控制權(quán),而C語(yǔ)言則把我們帶到了更高層次的,可以被人類閱讀的世界.雖然我們對(duì)編譯器失去了一點(diǎn)掌控,但我覺(jué)得出于我們的目的我們可以相信它.

????????我們需要由匯編語(yǔ)言開(kāi)頭,但是不用寫多少我們就會(huì)開(kāi)始使用C.

關(guān)于本教程的說(shuō)明

????????本教程并非教你使用匯編或者C.在這方面有充足的資源,而且我不是這方面的專家/權(quán)威!因此我將在這一過(guò)程中假設(shè)你有一些知識(shí).如果你想的話,請(qǐng)按照我介紹的主題進(jìn)行閱讀.

自舉代碼

????? 樹莓派最先運(yùn)行的代碼需要用匯編語(yǔ)言編寫.它做一些檢查和設(shè)置,然后啟動(dòng)我們的第一段C程序 - 內(nèi)核.

????????ARM Cortex A72 有4個(gè)核.我們只想讓我們的代碼在主核上運(yùn)行.所以我們檢查處理器ID并且運(yùn)行我們的代碼(主)或掛起一個(gè)無(wú)線循環(huán)(從).

????????我們需要告訴我們的操作系統(tǒng)如何訪問(wèn)棧.我把??醋魇钦趫?zhí)行的代碼所使用的臨時(shí)存儲(chǔ)空間,就像暫存板.我們需要為它留出內(nèi)存,并存儲(chǔ)一個(gè)指向它的指針。

????????我們還需要初始化一個(gè)BSS節(jié),這是內(nèi)存中用來(lái)存儲(chǔ)未初始化的變量的區(qū)域.在這里初始化更有效率,而不是在內(nèi)核鏡像中顯式的占用空間.

????????最終,我們可以跳轉(zhuǎn)到C語(yǔ)言的main()例程.

閱讀并理解下面的代碼,然后把他保存為 boot.S.我建議用?Arm Programmer's Guide ( 在ARM 官網(wǎng)上搜索?arm cortex-a series programmer's guide for armv8-a 即可得到相關(guān)文檔)?作為參考

.section ".text.boot"? // Make sure the linker puts this at the start of the kernel image


.global _start? // Execution starts here


_start:

? ? // Check processor ID is zero (executing on main core), else hang

? ? mrs? ? ?x1, mpidr_el1

? ? and? ? ?x1, x1, #3

? ? cbz? ? ?x1, 2f

? ? // We're not on the main core, so hang in an infinite wait loop

1:? wfe

? ? b? ? ? ?1b

2:? // We're on the main core!


? ? // Set stack to start below our code

? ? ldr? ? ?x1, =_start

? ? mov? ? ?sp, x1


? ? // Clean the BSS section

? ? ldr? ? ?x1, =__bss_start? ? ?// Start address

? ? ldr? ? ?w2, =__bss_size? ? ? // Size of the section

3:? cbz? ? ?w2, 4f? ? ? ? ? ? ? ?// Quit loop if zero

? ? str? ? ?xzr, [x1], #8

? ? sub? ? ?w2, w2, #1

? ? cbnz? ? w2, 3b? ? ? ? ? ? ? ?// Loop if non-zero


? ? // Jump to our main() routine in C (make sure it doesn't return)

4:? bl? ? ? main

? ? // In case it does return, halt the master core too

? ? b? ? ? ?1b

現(xiàn)在我們到C了

????????你應(yīng)該會(huì)注意到main()是未定義的,我們可以用C寫它(保存為 kernel.c),現(xiàn)在先讓讓它保持簡(jiǎn)潔.

void main(){

? ? while (1);

}

????????這讓我們陷入了一個(gè)無(wú)線循環(huán).

把它們鏈接起來(lái)

????????我們的代碼使用了兩種不同的語(yǔ)言.我們得想辦法把它們粘合在一起,確保所創(chuàng)造的鏡像文件可以按照我們計(jì)劃的方式執(zhí)行.我們使用鏈接腳本來(lái)完成這件事.鏈接腳本會(huì)定義BSS相關(guān)的標(biāo)簽,(可能你已經(jīng)在想它們?cè)谀睦锉欢x?),我建議你把它保存為link.ld

SECTIONS

{

? ? . = 0x80000;? ? ?/* Kernel load address for AArch64 */

? ? .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }

? ? .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }

? ? PROVIDE(_data = .);

? ? .data : { *(.data .data.* .gnu.linkonce.d*) }

? ? .bss (NOLOAD) : {

? ? ? ? . = ALIGN(16);

? ? ? ? __bss_start = .;

? ? ? ? *(.bss .bss.*)

? ? ? ? *(COMMON)

? ? ? ? __bss_end = .;

? ? }

? ? _end = .;


? ?/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }

}

__bss_size = (__bss_end - __bss_start)>>3;

????????寫鏈接腳本是值得研究的,但是為了我們的目的,你所需要知道的就是通過(guò)先引用 .text .boot 然后使用 KEEP() ,我們確保 .text 節(jié)從我們的匯編代碼開(kāi)始執(zhí)行.這意味著我們的首條指令在 0x80000 開(kāi)始執(zhí)行,它是樹莓派啟動(dòng)的時(shí)候會(huì)尋找到的地址.我們的代碼會(huì)被執(zhí)行.

????????現(xiàn)在你可以編譯,然后啟動(dòng)你的操作系統(tǒng)了!


Writing a "bare metal" operating system for Raspberry Pi 4 (Part 1)

How do we code?

We tell the RPi4 what to do by writing code. You may know that code ultimately ends up as a series of 0's and 1's (binary). You'll be pleased to know, however, that we don't need to write it like this, otherwise we'd easily lose track of what was going on! In fact, it's one of the jobs of the compiler to convert human-readable language into those 0's and 1's.


To get going we need to understand two languages: **assembly language** and **C**. Whilst C will likely be recognisable to most modern software developers, assembly language is "spoken" by fewer folks. It's a lower-level language that most closely resembles how the CPU "thinks" and it therefore gives us a lot of control, whereas C brings us into a higher-level, human-readable world. We lose a little control to the compiler though, but for our purposes I think we can trust it!


We will need to start out in assembly language, but there isn't much to write before we can then pick up in C.


A note about this tutorial

This tutorial is not intended to teach you how to code in assembly language or C. There are plenty of good resources on these topics and I am not an expert/authority! I will therefore be assuming some knowledge along the way. Please do read around the topics that I introduce if you need/want to.


Bootstrapping

The first code that the RPi4 will run will need to be written in assembly language. It makes some checks, does some setup and launches us into our first C program - the **kernel**.


?* The Arm Cortex-A72 has four cores. We only want our code to run on the master core, so we check the processor ID and either run our code (master) or hang in an infinite loop (slave).

?* We need to tell our OS how to access the **stack**. I think of the stack as temporary storage space used by currently-executing code, like a scratchpad. We need to set memory aside for it and store a pointer to it.

?* We also need to initialise the BSS section. This is the area in memory where uninitialised variables will be stored. It's more efficient to initialise everything to zero here, rather than take up space in our kernel image doing it explicitly.

?* Finally, we can jump to our main() routine in C!


Read and understand the code below and save it as _boot.S_. I suggest using the [Arm Programmer's Guide](https://developer.arm.com/documentation/den0024/a/) as a reference.



.section ".text.boot"? // Make sure the linker puts this at the start of the kernel image


.global _start? // Execution starts here


_start:

? ? // Check processor ID is zero (executing on main core), else hang

? ? mrs? ? ?x1, mpidr_el1

? ? and? ? ?x1, x1, #3

? ? cbz? ? ?x1, 2f

? ? // We're not on the main core, so hang in an infinite wait loop

1:? wfe

? ? b? ? ? ?1b

2:? // We're on the main core!


? ? // Set stack to start below our code

? ? ldr? ? ?x1, =_start

? ? mov? ? ?sp, x1


? ? // Clean the BSS section

? ? ldr? ? ?x1, =__bss_start? ? ?// Start address

? ? ldr? ? ?w2, =__bss_size? ? ? // Size of the section

3:? cbz? ? ?w2, 4f? ? ? ? ? ? ? ?// Quit loop if zero

? ? str? ? ?xzr, [x1], #8

? ? sub? ? ?w2, w2, #1

? ? cbnz? ? w2, 3b? ? ? ? ? ? ? ?// Loop if non-zero


? ? // Jump to our main() routine in C (make sure it doesn't return)

4:? bl? ? ? main

? ? // In case it does return, halt the master core too

? ? b? ? ? ?1b

```


And now we're in C

You will likely note that the `main()` routine is as yet undefined. We can write this in C (save it as _kernel.c_), keeping it very simple for now:


```c

void main()

{

? ? while (1);

}

```


This simply spins us in an infinite loop!


Linking it all together

We've written code in two different languages. Somehow we need to glue these together, ensuring that the created image will be executed in the way that we intend. We use a **linker script** for this. The linker script will also define our BSS-related labels (perhaps you were already wondering where they get defined?). I suggest you save the following as _link.ld_:


```c

SECTIONS

{

? ? . = 0x80000;? ? ?/* Kernel load address for AArch64 */

? ? .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }

? ? .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }

? ? PROVIDE(_data = .);

? ? .data : { *(.data .data.* .gnu.linkonce.d*) }

? ? .bss (NOLOAD) : {

? ? ? ? . = ALIGN(16);

? ? ? ? __bss_start = .;

? ? ? ? *(.bss .bss.*)

? ? ? ? *(COMMON)

? ? ? ? __bss_end = .;

? ? }

? ? _end = .;


? ?/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }

}

__bss_size = (__bss_end - __bss_start)>>3;

```


Writing linker scripts is [worth investigating](http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_mono/ld.html#SEC6) but, for our purposes, all you need to know is that by referencing `.text.boot` first and using the `KEEP()`, we ensure the `.text` section starts with our assembly code. That means our first instruction starts at 0x80000, which is exactly where the RPi4 will look for it when it boots. Our code will be run.


_Now you're ready to compile and then boot your OS!_




03-對(duì)part1-bootstrapping的搬運(yùn)和翻譯的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
铅山县| 宽甸| 青州市| 辽中县| 龙山县| 丹巴县| 吐鲁番市| 黄浦区| 南召县| 上思县| 陕西省| 务川| 克拉玛依市| 高台县| 于田县| 乌兰察布市| 唐海县| 西贡区| 开远市| 崇州市| 县级市| 和平县| 唐河县| 平邑县| 南靖县| 石家庄市| 怀安县| 五台县| 玛沁县| 冕宁县| 义马市| 准格尔旗| 千阳县| 舞钢市| 长子县| 武定县| 余江县| 青铜峡市| 高青县| 张家口市| 酒泉市|