/** 代码演示 - 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 返回上次跳转之前的位置
新闻热点
疑难解答
图片精选