/** 代碼演示 - les.s **/.text.global _start.code 32@ 定義三個控制led燈的GPIO寄存器.equ GPIOC_OUT, 0xc001c000.equ GPIOC_OUTENB, 0xc001c004.equ GPIOC_ALTFN0, 0xc001c020_start: @ 功能選擇 FUNCTION1 ldr r0, =GPIOC_ALTFN0 @ r0=0xc001c020 ldr r1, [r0] @ r0放到r1作為緩存 mov r2, #0x03 bic r1, r1, r2, lsl #24 @ clear r1 [25:24] mov r2, #1 orr r1, r1, r2, lsl #24 @ set r1 [24] str r1, [r0] @ 寫回r0寄存器GPIOC_ALFN0 @ 配置為輸出功能 ldr r0, =GPIOC_OUTENB @ r0=0xc001c004 ldr r1, [r0] mov r2, #1 orr r1, r1, r2, lsl #12 @ set r1 [12] str r1, [r0] @ 寫回r0寄存器GPIOC_OUTENB mov r2, #1loop: @ 亮燈 ldr r0, =GPIOC_OUT @ r0=0xc001c000 ldr r1, [r0] bic r1, r1, r2, lsl #12 @ clear r1 [12] str r1, [r0] bl delay @ 調用函數delay @ 滅燈 ldr r0, =GPIOC_OUT @ r0=0xc001c000 ldr r1, [r0] orr r1, r1, r2, lsl #12 @ set r1 [12] str r1, [r0] bl delay b loop @ b跳轉loop循環 - led間歇閃爍delay: mov r0, #0x8000000 @ 設置延時,值較C語言大,因速度快delay_loop: sub r0, r0, #1 @ r0=r0-1 cmp r0, #0 @ 比較 r0 與 0 bne delay_loop @ 不相等,b跳轉自身循環繼續-- mov pc, lr @ bx lr 壓棧.end/** ------------------------------------------------------- **/4、C和匯編的混合調用 ATPCS // ARM體系結構與編程.pdf --->P241. 1)使用的滿減棧 FD 2)函數參數的傳遞,前4個參數使用 r0 r1 r2 r3剩余參數使用棧傳遞 3)函數返回時,返回值使用r04.1 匯編中如何調用C函數 xxx.s - 匯編 .extern func @// 使用extern聲明func標號為外部函數 mov r0, #5 @// r0 里面最終會保存函數的返回值 mov r1, #10 bl func @// bl 調用func函數,傳遞參數5和10 yyy.c - C程序 int func (int a, int b) { return a + b; }4.2 C程序中如何調用匯編函數 yyy.c - C程序 extern int func (int, int); func (10, 20); xxx.s - 匯編 .global func @// 必要條件 func: add r0, r0, r1 mov pc, lr4.3 C程序中嵌套匯編語法練習: shell框架程序。 使用匯編實現led.c里面的函數 - led.s。' vi Makefile 新增arm的as編譯匯編文件變量 AS=arm-cortex_a9-linux-gnueabi-as %.o:%.s $(AS) $< -o $@/** 代碼演示 **/.text.global led_init.global led_on.global led_off.code 32.extern uart_puts @// 打印字符換來做調試使用.equ GPIOC_OUT, 0xc001c000.equ GPIOC_OUTENB, 0xc001c004.equ GPIOC_ALTFN0, 0xc001c020led_init: stmfd sp!, {lr} @// 把lr壓棧,保證lr是原來的值 ldr r0, =str1 @// 將str1的首地址放到r0里面 bl uart_puts @// 調用uart_puts函數來打印顯示 @ 功能選擇 FUNCITON1 ldr r0, =GPIOC_ALTFN0 @ r0=0xc001c020 ldr r1, [r0] mov r2, #0x03 bic r1, r1, r2, lsl #24 @ clear r1 [25:24] mov r2, #1 orr r1, r1, r2, lsl #24 @ set r1 [24] str r1, [r0] @ 配置為輸出功能 ldr r0, =GPIOC_OUTENB @ r0=0xc001c004 ldr r1, [r0] mov r2, #1 orr r1, r1, r2, lsl #12 @ set r1 [12] str r1, [r0] mov pc, lr @ 壓棧,相當于函數返回return @// ldmfd sp!, {lr} 打印調試信息,使用此句彈棧led_on: mov r2, #1 @ 把1放在r2寄存器緩沖區 ldr r0, =GPIOC_OUT @ r0=0xc001c000 ldr r1, [r0] bic r1, r1, r2, lsl #12 @ clear r1 [12] - 低電平 - 亮 str r1, [r0] mov pc, lrled_off: mov r2, #1 ldr r0, =GPIOC_OUT ldr r1, [r0] orr r1, r1, r2, lsl #12 @ set r1 [12] - 高電平 - 亮 str r1, [r0] mov pc, lrstr1: .string "/nled_init/0".end/** ------------------------------------------------------- **/練習二: 使用匯編指令將strcmp.c替換為strcmp.s的匯編文件。/** 代碼演示 - strcmp.s **/.text.code 32.global my_strcmpmy_strcmp:cmp_loop: ldrb r2, [r0], #1 @ // 每次取1個字符出來放到r2寄存器 ldrb r3, [r1], #1 @ // 每次取1個字符出來放到r3寄存器 cmp r2, #0 @ // 判斷r2是否到末尾 beq cmp_end @ // 如果r2==0到末尾,就跳轉到cmp_end cmp r2, r3 @ // beq cmp_loopcmp_end: sub r0, r2, r3 mov pc, lr @ // <==> bx lr.end/** ------------------------------------------------------- **/<tips>$:' cd 01/$:'ctags -R *$:' vi main.c // 打開最開始的一個文件' 光標移動到函數或者變量名字上'Ctrl + ] 跳轉到定義/實現位置'Ctrl + t 返回上次跳轉之前的位置
新聞熱點
疑難解答
圖片精選