首页 > 编程 > ASM > 正文

ARM:伪指令、伪操作、C和汇编混合操作、汇编控制LED

2019-11-08 02:12:56
字体:
来源:转载
供稿:网友
1、伪指令    指令本身不被ARM core所识别    但是汇编器可以把伪指令翻译成一条或多条ARM core认识的指令1.1 【ldr】---> 重点掌握    作用1:'将立即数存储到特定寄存器中,(汇编代码中使用=的)                mov r0, #0x1ff                可以使用                ldr r0, =0x1ff                _start:                    ldr r0, =0x1ff                    ldr r1, =lable  // 将lable对应的地址加载到r1                    b .                    .end                arm-co...-as pesdo.s -o pesdo.o                arm-co...-objdump -S pwsdo.o > 1.asm    作用2:'将lable标签对应内存中的数据加载到寄存器(汇编代码中同时没有使用=和[ ]的)                ldr r2, lable1.2 【adr】    作用:'小范围地址加载指令   ADR{cond} register, exPR    adr 可以找到标号对应代码在内存中的位置    adr r3, delay  @// sub r3, pc, #4    delay:            mov r5, r6    1.3 【nop】    作用:'空操作,用于延时    一般会被编译器翻译为 mov r0, r02、伪操作    '以 . 开头的都是伪操作    .arm  /  .code 32   / .thumb  / .code 16   // arm或thumb汇编指令    .equ// 常量定义伪操作            .equ NUM, #0x20            mov r0, NUM    .global  / .globl  // 将一个标号声明为声明全局的常量伪操作    .extern  // 声明外部常量伪操作    .hWord / .short // 半字定义伪操作    .word / .int / .long // 字定义伪操作    .byte // 字节定义伪操作    .string "abcde" / .ascii "abcde" / .asciz "abcde" // 字符串定义伪操作    .space 1024  / .skip 1024 // 固定填充字节内存单元定义伪操作3、使用汇编控制LED    电路原理图:        控制LED1就是控制GPIOC12    控制GPIOC12: 3 个特殊功能寄存器        GPIOC_OUT          0xc001c000        GPIOC_OUTENB    0xc001c004        GPIOC_ALTFN0      0xc001c020    使用汇编代码编写:led.s
/** 代码演示  - 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         返回上次跳转之前的位置
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选