要移植作業系統,彙編是道不得不跨過去的坎。所以承接上篇的思路,我準備用彙編寫乙個簡單的閃爍led燈的程式。以此練習彙編,為作業系統做準備。
第一步,還是和上篇一樣,建立乙個空的資料夾。
第二步,因為是要用彙編來寫程式,所以不需要啟動**,這裡選擇否。
第三步,建立乙個.s檔案,並把檔案新增到工程中。
第四步,在led.s檔案中新增如下**。
led0 equ 0x422101a0**的簡單講解rcc_apb2enr equ 0x40021018
gpioa_crh equ 0x40010804
stack_size equ 0x00000400
area stack, noinit, readwrite, align=3
stack_mem space stack_size
__initial_sp
area reset, data, readonly
__vectors dcd __initial_sp ; top of stack
dcd reset_handler ; reset handler
area |.text|, code, readonly
thumb
require8
preserve8
entry
reset_handler
bl led_init
mainloop bl led_on
bl delay
bl led_off
bl delay
b mainloop
led_init
push
ldr r0,=rcc_apb2enr
orr r0,r0,#0x04
ldr r1,=rcc_apb2enr
str r0,[r1]
ldr r0,=gpioa_crh
bic r0,r0,#0x0f
ldr r1,=gpioa_crh
str r0,[r1]
ldr r0,=gpioa_crh
orr r0,r0,#0x03
ldr r1,=gpioa_crh
str r0,[r1]
mov r0,#1
ldr r1,=led0
str r0,[r1]
pop
led_on
push
mov r0,#0
ldr r1,=led0
str r0,[r1]
pop
led_off
push
mov r0,#1
ldr r1,=led0
str r0,[r1]
pop
delay
push
movs r0,#0
movs r1,#0
movs r2,#0
delayloop0
adds r0,r0,#1
cmp r0,#330
bcc delayloop0
movs r0,#0
adds r1,r1,#1
cmp r1,#330
bcc delayloop0
movs r0,#0
movs r1,#0
adds r2,r2,#1
cmp r2,#15
bcc delayloop0
pop
; nop
end
1,預定義
led0 equ 0x422101a0 ;pa8的bit-bond位址。
rcc_apb2enr equ 0x40021018
gpioa_crh equ 0x40010804
為方便操作,給每個需要用到的暫存器位址定義乙個名字,類似於c語言的#define。pa8的bit-bond位址的計算方法可按上篇文章中c語言的演算法算出。後面的兩個位址時固定的,可從stm32的手冊查詢,或者根據st官方的庫檔案查詢計算。
2,分配棧空間
stack_size equ 0x00000400
area stack, noinit, readwrite, align=3
stack_mem space stack_size
__initial_sp
這一段摘自啟動檔案。要讀懂這段**,首先要了解兩個命令。
area 段名,段屬性1,段屬性2,段屬性3。。。
area stack, noinit, readwrite, align=3
noinit: = no init,不初始化。
readwrite : 可讀,可寫。
align =3 : 2^3 對齊,即8位元組對齊。
space命令:space 命令保留乙個用零填充的儲存器塊。
3,分配向量表
area reset, data, readonly
__vectors dcd __initial_sp ; top of stack
dcd reset_handler ; reset handler
這裡的向量可參考我之前寫的《stm32向量表詳細分析》。
4,開始**段
area |.text|, code, readonly
通知彙編器,開始**段。
thumb
require8
preserve8
這段的意思是,彙編器支援thumb指令,**段按8位元組對齊。
entry命令:宣告整個程式的入口點,入口點有且僅有乙個。不管哪種語言,編譯器都得有個入口點,這沒什麼好說的。
5,程式正式開始。
後面的**,皆用標準的thumb2彙編指令。首先了解下**中用到的指令。
b:無條件跳轉。
push和pop:可以看到,所有的子程式都是由push和pop包起來的。借用一張**釋下這兩個指令。
據上可知,push 的意思即把r0,r1,lr中的值放入堆疊中。由於主程式中使用bl跳轉指令,所以lr中的值實際上就是當前pc的值。而pop 的意思即是將棧中之前存的r0,r1,lr的值返還給r0,r1,pc。這樣就完成了子程式的返回。
ldr和str:暫存器的裝載和儲存指令。
ldr是把位址裝載到暫存器中(比如r0)。
str是把值儲存到暫存器所指的位址中。
舉個例子:
mov r0,#1 ;將立即數1送入r0.
ldr r1,=led0;將pa8 bit-bond的位址送入r1.
str r0,[r1];將r0的值,也就是1,送給r1中的值所指向的位址中,也就是pa8的bit-bond位址。
上面三句話的意思即是將pa8置1。
orr和bic:
orr 按位或操作。orr r0,r0,#0x04意思即將r0中的數或上0x04,再將結果送往r0中。實際意思就是將r0的第二位置1,其他位不變。
bic 先把立即數取反,再按位與。
cmp和bcc:cmp是比較兩個數,相等或大於則將標誌位c置位,否則將c清零。bcc是個組合指令,實際為b+cc,意思是如果c=0則跳轉。
cmp r2,#15; 計算r2-15的值,若是r2<15,則c=0;若是r2>=15,則c=1。
bcc delayloop0;若是c=0,則跳到delayloop0,若是c=1,則不跳轉。
以上就是**段相關指令的介紹,相信了解了這些指令的含義,要理解**並不困難。
整個**的結構和上篇用c語言寫的基本是一樣的。可參照理解
STM32彙編程式設計
1.實驗環境 1.野火stm32指南者 stm32f103vet6 2.keil5 2.環境搭建新建工程 新增原始檔 s 連線開發板,開始debug 生成的hex檔案 原始碼led0 equ 0x40010c00 rcc apb2enr equ 0x40021018 gpioa crh equ 0x...
stm32工程建立
1.新建乙個檔案,夾命名為proname.在該資料夾下新建四個資料夾,分別是 src 存放自己編寫的原始碼 project 存放工程檔案 output 存放輸出檔案 listing 存放listing檔案 3.點,設定工程檔案結構,包括 startup 包含啟動檔案 乙個.s檔案,具體根據晶元型號來...
STM32的LED燈實驗
實驗目的 讓我的開發板的led燈亮滅閃爍 實驗程式 led.c include stm32f4xx.h 在system目錄下可以找到,把st官方的部分庫抽取出來,組成了乙個system目錄 include sys.h void led init void led.h ifndef led h def...