国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

專題10-C語(yǔ)言環(huán)境初始化

2019-11-08 18:22:33
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

bootloader的第二部分代碼主要是采用C語(yǔ)言來(lái)實(shí)現(xiàn)的,利用C語(yǔ)言實(shí)現(xiàn)串口、網(wǎng)卡等功能,并成功啟動(dòng)操作系統(tǒng)

一、棧的初始化

1、概念解析

棧:先進(jìn)后出性質(zhì)的數(shù)據(jù)組織方式 棧底:第一個(gè)進(jìn)棧的數(shù)據(jù)所處位置 棧頂:最后一個(gè)進(jìn)棧的數(shù)據(jù)所處位置

滿棧:當(dāng)堆棧指針SP總是指向最后壓入堆棧的數(shù)據(jù) 空棧:當(dāng)堆棧指針SP指向下一個(gè)將要放入數(shù)據(jù)的空位置 這里寫圖片描述 升棧:隨著數(shù)據(jù)的入棧,SP指針從 低地址–》高低址 降棧:隨著數(shù)據(jù)的入棧,SP指針從 高地址–》低低址 這里寫圖片描述 棧幀:就是一個(gè)函數(shù)所使用的那部分棧(R11寄存器,也就是棧幀寄存器FP) 所有函數(shù)的棧幀串起來(lái)組成就是一個(gè)完整的棧,在堆棧指針SP(下邊界)與棧幀指針FP(上邊界)之間就是棧區(qū)。

ARM采用 滿降棧!!

2、手把手帶你分析

棧的作用:

2、1 保存局部變量保存

//stack1.c#include <stdio.h>int main(){ int a; a++; return a;}//在sheel里面運(yùn)行實(shí)例程序stack1.carm-linux-gcc -g stack1.c -o stack1arm-linux-objdump -D -S stack1 >dump1 //反匯編vim dump1 //進(jìn)入文件后,在:中搜索關(guān)鍵字,例如: :/main

進(jìn)入dump后可以結(jié)合匯編代碼,可知a是存儲(chǔ)在棧幀指針fp和堆棧指針sp之間的。如圖: 這里寫圖片描述

2、2 傳遞參數(shù)

當(dāng)函數(shù)的參數(shù)大于 4個(gè)的時(shí)候,將使用棧來(lái)傳遞參數(shù)。

//stack2.c#include <stdio.h>void func1(int a,int b,int c,int d,int e,int f){ int k; k=e+f;}int main(){ func1(1,2,3,4,5,6); return 0;}//在sheel里面運(yùn)行實(shí)例程序stack2.carm-linux-gcc -g stack2.c -o stack2arm-linux-objdump -D -S stack2 >dump2 //反匯編vim dump2

這里寫圖片描述 這里寫圖片描述

3.3 保存寄存器的值

#include <stdio.h>void func2(int a,int b){ int k; k=a+b;}void func1(int a,int b){ int c; func2(3,4); c=a+b;}int main(){ func1(1,2); return 0;}//在sheel里面運(yùn)行實(shí)例程序stack3.carm-linux-gcc -g stack3.c -o stack3arm-linux-objdump -D -S stack3 >dump3 //反匯編vim dump3

這里寫圖片描述 這里寫圖片描述

3、初始化堆棧

不管是2440還是6410還是210,將sp指針指向64M內(nèi)存(保證夠用)的地方,在使用的過(guò)程中,sp向下移(因?yàn)锳RM中采用的降棧)。 2440:0x30000000+64M = 0x34000000 6410:0x50000000+64M 210 :0x20000000+64M

//2440的堆棧初始化init_stack: ldr sp, =0x34000000 mov pc ,lr

二、bss段初始化

未初始化的全局變量 分析驗(yàn)證代碼如下:

//bss.c#include <stdio.h>int year;int main(){ year = 2017; return year;}//在sheel里面輸入arm-linux-gcc -g bss.c -o bssarm-linux-readelf -a bss >dumpvi dump //然后:/year

由下圖結(jié)果可知,未初始化的全局變量處于bss段之間: 這里寫圖片描述

如果存在bss段的內(nèi)容沒有賦值而直接采用,則里面存儲(chǔ)的值可能是亂碼,為了確保軟件質(zhì)量,所以一般要有清零操作。

clean_bss: ldr r0, =bss_start //bss_start和bss_end是在鏈接器腳本gboot.lds中定義的 ldr r1, =bss_end cmp r0, r1 moveq pc, lr //若r0和r1相等,則直接返回,否則展開清零工作clean_loop: mov r2, #0 str r2, [r0], #4 cmp r0, r1 bne clean_loop mov pc, lr

三、跳轉(zhuǎn)到C大門

采用絕對(duì)方式跳轉(zhuǎn)。 定義文件main.c

int gboot_main(){ return 0;}

在start.s中加上:

ldr pc, =goot_main

修改Makefile:

這里寫圖片描述

因?yàn)橹笆窃趨R編中點(diǎn)亮led的(起一個(gè)驗(yàn)證代碼是否正確的作用),現(xiàn)在為了驗(yàn)證程序能不能正確跳轉(zhuǎn)到main.c中,可以將點(diǎn)亮led的代碼移植到main.c中:

請(qǐng)注意:(volatile unsigned long*)的書寫方式。

//main.c#define GPBCON (volatile unsigned long*)0x56000010#define GPBDAT (volatile unsigned long*)0x56000014int gboot_main(){ *(GPBCON) = 0x400; *(GPBDAT) = 0x0; return 0; }

之前匯編中的代碼如下:

bl light_led...light_led: #define GPBCON 0x56000010 #define GPBDAT 0x56000014 light_led: ldr r0, =GPBCON mov r1, #0x400 str r1, [r0] ldr r0, =GPBDAT mov r1, #0x0 str r1, [r0] mov pc, lr

將上面的bl light_led備注掉,即@bl light_led。注意匯編中的注釋符號(hào)是“”@“”。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 务川| 南陵县| 江达县| 青阳县| 汉阴县| 军事| 金秀| 咸阳市| 淮滨县| 辽源市| 津市市| 呼和浩特市| 佛教| 普定县| 通州市| 阿瓦提县| 奉贤区| 临安市| 怀来县| 新和县| 阳新县| 武宣县| 什邡市| 钟祥市| 望江县| 长宁区| 沧源| 平远县| 阜新市| 德令哈市| 扶绥县| 旺苍县| 银川市| 广河县| 临猗县| 睢宁县| 曲松县| 广州市| 莱州市| 穆棱市| 汉中市|