博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C函数调用
阅读量:6296 次
发布时间:2019-06-22

本文共 3396 字,大约阅读时间需要 11 分钟。

目录


title: C函数调用

tags: ARM
date: 2018-10-14 16:37:10
---

C函数调用

设置SP

C函数启动需要设置堆栈,因为局部变量都是存在堆栈的,函数调用也需要栈

但是2440中NAND启动和NOR启动的时候,片内RAM的地址是不一样的.

  • NOR,0x4000,0000+4K
  • NAND,0+4K

SP分析

从NAND启动的代码分析

//start.S//.text.global _start_start:    /* 设置内存: sp 栈 */    ldr sp, =4096               /* nand启动 */    //ldr sp, =0x40000000+4096  /* nor启动 */    /* 调用main */    bl mainhalt:    b halt///main.c///int main(){    unsigned int *pGPFCON = (unsigned int *)0x56000050;    unsigned int *pGPFDAT = (unsigned int *)0x56000054;    /* 配置GPF4为输出引脚 */    *pGPFCON = 0x100;        /* 设置GPF4输出0 */    *pGPFDAT = 0;    return 0;}//makefile/all:    arm-linux-gcc -c -o led.o led.c    arm-linux-gcc -c -o start.o start.S    arm-linux-ld -Ttext 0 start.o led.o -o led.elf    arm-linux-objcopy -O binary -S led.elf led.bin    arm-linux-objdump -D led.elf > led.disclean:    rm *.bin *.o *.elf *.dis

查看下反汇编的代码

led.elf:     file format elf32-littlearmDisassembly of section .text:00000000 <_start>:   0:   e3a0da01    mov sp, #4096   ; 0x1000   4:   eb000000    bl  c 
00000008
: 8: eafffffe b 8
0000000c
: c: e1a0c00d mov ip, sp 10: e92dd800 stmdb sp!, {fp, ip, lr, pc} 14: e24cb004 sub fp, ip, #4 ; 0x4 18: e24dd008 sub sp, sp, #8 ; 0x8 1c: e3a03456 mov r3, #1442840576 ; 0x56000000 20: e2833050 add r3, r3, #80 ; 0x50 24: e50b3010 str r3, [fp, #-16] 28: e3a03456 mov r3, #1442840576 ; 0x56000000 2c: e2833054 add r3, r3, #84 ; 0x54 30: e50b3014 str r3, [fp, #-20] 34: e51b2010 ldr r2, [fp, #-16] 38: e3a03c01 mov r3, #256 ; 0x100 3c: e5823000 str r3, [r2] 40: e51b2014 ldr r2, [fp, #-20] 44: e3a03000 mov r3, #0 ; 0x0 48: e5823000 str r3, [r2] 4c: e3a03000 mov r3, #0 ; 0x0 50: e1a00003 mov r0, r3 54: e24bd00c sub sp, fp, #12 ; 0xc 58: e89da800 ldmia sp, {fp, sp, pc}Disassembly of section .comment:00000000 <.comment>: 0: 43434700 cmpmi r3, #0 ; 0x0 4: 4728203a undefined 8: 2029554e eorcs r5, r9, lr, asr #10 c: 2e342e33 mrccs 14, 1, r2, cr4, cr3, {1} 10: Address 0x10 is out of bounds.

main函数的流程

  1. 保存sp
  2. 保存lr和pc,以及会被改变的寄存器的值
  3. 数据处理完后把寄存器恢复

汇编解析

LDMED    LDMIB    预先增加装载LDMFD    LDMIA    过后增加装载LDMEA    LDMDB    预先减少装载LDMFA    LDMDA    过后减少装载STMFA    STMIB    预先增加存储STMEA    STMIA    过后增加存储STMFD    STMDB    预先减少存储STMED    STMDA    过后减少存储

mark

区分NAND和NOR启动

NAND启动的时候,代码是在NAND中,但实际上是上电自动copy代码到片内RAM,也就是实际是在片内RAM运行,可读可写.通过判断0地址是否可写即可判断

//1.读出0地址的值备份到r0mov r1,#0ldr r0,[r1]//r1=0//2.在0地址写入0//把r1的值写入[r1]所在内存str r1,[r1]//3.读出0地址的值ldr r2,[r1]//4.比较 写入的值和读出的值cmp r2,r1ldr sp, =0x40000000+4096 /* 先假设是nor启动 *///如果相等则是nand启动moveq sp, #4096  /* nand启动 */streq r0, [r1]   /* 恢复原来的值 */

完整调用如下

.text.global _start_start:    /* 关闭看门狗 */    ldr r0, =0x53000000    ldr r1, =0    str r1, [r0]    /* 设置内存: sp 栈 */    /* 分辨是nor/nand启动     * 写0到0地址, 再读出来     * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动     * 否则就是nor启动     */    mov r1, #0    ldr r0, [r1] /* 读出原来的值备份 */    str r1, [r1] /* 0->[0] */     ldr r2, [r1] /* r2=[0] */    cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */    ldr sp, =0x40000000+4096 /* 先假设是nor启动 */    moveq sp, #4096  /* nand启动 */    streq r0, [r1]   /* 恢复原来的值 */        bl mainhalt:    b halt

参数调用

遵循ATPCS原则,r0~r4存放参数,lr为返回地址,参考

转载于:https://www.cnblogs.com/zongzi10010/p/10023525.html

你可能感兴趣的文章
Android SharedPreferences
查看>>
css面试题
查看>>
Vue组建通信
查看>>
用CSS画一个带阴影的三角形
查看>>
前端Vue:函数式组件
查看>>
程鑫峰:1.26特朗.普力挺美元力挽狂澜,伦敦金行情分析
查看>>
safari下video标签无法播放视频的问题
查看>>
01 iOS中UISearchBar 如何更改背景颜色,如何去掉两条黑线
查看>>
对象的继承及对象相关内容探究
查看>>
Spring: IOC容器的实现
查看>>
Serverless五大优势,成本和规模不是最重要的,这点才是
查看>>
Nginx 极简入门教程!
查看>>
iOS BLE 开发小记[4] 如何实现 CoreBluetooth 后台运行模式
查看>>
Item 23 不要在代码中使用新的原生态类型(raw type)
查看>>
为网页添加留言功能
查看>>
JavaScript—数组(17)
查看>>
Android 密钥保护和 C/S 网络传输安全理论指南
查看>>
以太坊ERC20代币合约优化版
查看>>
Why I Began
查看>>
同一台电脑上Windows 7和Ubuntu 14.04的CPU温度和GPU温度对比
查看>>