C函数调用
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 main
halt:
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.dis
clean:
rm *.bin *.o *.elf *.dis
查看下反汇编的代码
led.elf: file format elf32-littlearm
Disassembly of section .text:
00000000 <_start>:
0: e3a0da01 mov sp, #4096 ; 0x1000
4: eb000000 bl c <main>
00000008 <halt>:
8: eafffffe b 8 <halt>
0000000c <main>:
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函数的流程
- 保存sp
- 保存lr和pc,以及会被改变的寄存器的值
- 数据处理完后把寄存器恢复
汇编解析
LDMED LDMIB 预先增加装载
LDMFD LDMIA 过后增加装载
LDMEA LDMDB 预先减少装载
LDMFA LDMDA 过后减少装载
STMFA STMIB 预先增加存储
STMEA STMIA 过后增加存储
STMFD STMDB 预先减少存储
STMED STMDA 过后减少存储

区分NAND和NOR启动
NAND启动的时候,代码是在NAND中,但实际上是上电自动copy代码到片内RAM,也就是实际是在片内RAM运行,可读可写.通过判断0地址是否可写即可判断
//1.读出0地址的值备份到r0
mov r1,#0
ldr r0,[r1]
//r1=0
//2.在0地址写入0
//把r1的值写入[r1]所在内存
str r1,[r1]
//3.读出0地址的值
ldr r2,[r1]
//4.比较 写入的值和读出的值
cmp r2,r1
ldr 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 main
halt:
b halt
参数调用
遵循ATPCS原则,r0~r4存放参数,lr为返回地址,参考ATPCS规则.md
C函数调用的更多相关文章
- idapython实现动态函数调用批量注释
部门小伙伴遇到一个样本需要对动态函数调用就行批量注释还原的问题,通过idapython可以大大的减少工作量,其实这一问题也是很多样本分析中最耗时间的一块,下面来看看如何解决这个问题(好吧这才是今年最后 ...
- [汇编与C语言关系]1.函数调用
对于以下程序: int bar(int c, int d) { int e = c + d; return e; } int foo(int a, int b) { return bar(a, b); ...
- javascript函数调用的各种方法!!
在JavaScript中一共有下面4种调用方式: (1) 基本函数调用 (2)方法调用 (3)构造器调用 (4)通过call()和apply()进行调用 1. 基本函数调用 普通函数调用模式,如: J ...
- jsContext全局函数调用与对象函数调用、evaluateScript
evaluateScript:兼具js加载(生成具体的上下文)(函数与通用变量的加载),与函数执行的功能: 函数调用的方式有两种: 1)获取函数(对象),然后执行调用: [context[@" ...
- 用 Graphviz+pvtrace 可视化函数调用
最近在想怎么把一个程序的函数调用关系快速的用流程图的方式画出来,之后看到了这个一篇文章“用 Graphviz 可视化函数调用”(http://www.ibm.com/developerworks/cn ...
- 行内js函数调用
<ul> <li onclick=abc(this);><a href="javascript:void(0);">12234588</a ...
- ObReferenceObjectByName函数调用WIN7下的解决
<寒江独钓 Windows内核安全编程>第4章键盘的过滤ctrl2cap代码中,ObReferenceObjectByName函数调用: [1]extern POBJECT_TYPE Io ...
- c语言函数, 函数调用及函数递归
1. 函数的定义: 返回值类型 函数名(形参列表) {函数体(函数的实现内容)}, 注意: 如果没有参数, 小括号也是必不可少的. 函数与函数之间可以嵌套调用(也就是在一个函数内部可以调用另外一个函 ...
- C/C++函数调用的几种方式及函数名修饰规则以及c++为什么不允许重载仅返回类型不同的函数
我们知道,调用函数时,计算机常用栈来存放函数执行需要的参数,由于栈的空间大小是有限的,在windows下栈是向低地址扩展的数据结构,是一块连续的内存区域.这句话的意思是栈顶的地址和栈的最大容量是系统预 ...
- 深入理解 C 语言的函数调用过程
来源: wjlkoorey 链接:http://blog.chinaunix.net/uid-23069658-id-3981406.html 本文主要从进程栈空间的层面复习一下C语言中函数调用的具体 ...
随机推荐
- 日期T转换
日期转换 在startup.csd ConfigureServices方法里 services.AddMvc().AddJsonOptions(o => { o.SerializerSettin ...
- Codeforces Round #429 Div. 1
A:甚至连题面都不用仔细看,看一下样例就知道是要把大的和小的配对了. #include<iostream> #include<cstdio> #include<cmath ...
- webpack——阮一峰webpackDemo分析
首先上交阮一峰老师的github地址,一共有15个demo,我们一个一个的进行分析,结合上文所学的知识! 其中有一些内容,我做了修改,我是先看一遍然后从新敲了一遍. https://github.co ...
- 用递归方法判断字符串是否是回文(Recursion Palindrome Python)
所谓回文字符串,就是一个字符串从左到右读和从右到左读是完全一样的.比如:"level" .“aaabbaaa”. "madam"."radar&quo ...
- django 报错 : django.core.exceptions.ImproperlyConfigured: The STATICFILES_DIRS setting should not contain the STATIC_ROOT setting
错误原因有可能是在settings中静态文件目录设置的有问题 STATIC_ROOT=os.path.join(BASE_DIR,"static/")#错误 STATIC_ROOT ...
- 【BZOJ4832】抵制克苏恩(矩阵快速幂,动态规划)
[BZOJ4832]抵制克苏恩(矩阵快速幂,动态规划) 题面 BZOJ 题解 一模一样 #include<iostream> #include<cstdio> using na ...
- 超详解的LNMP搭建并优化
环境为Centos7 nginx1.14 mysql5.7 php7一,安装Nginx (yum装,快速) yum install nginx二,优化nginx (方便后期工作,如果纯为测试的话,不用 ...
- HDU46093-idiots
题目大意 给一堆边的长度,问从中随机选出三条边来能够组成三角形的概率. 题解 其实就是要求能够组成三角形的方案数.直接从三条边入手问题会很复杂,所以我们可以先求出f[x]表示随便选出两条边长度之和为x ...
- numpy ndarray求其最值的索引
import numpy as np a = np.array([1,2,3,4]) np.where(a== np.max(a)) >>>3 但假设其最值不止一个,如下 a = n ...
- 20165223 《JAVA程序设计》第六周学习总结
教材学习内容总结 第八章-常用实用类-要点 基础:String类 重点:StringTokenizer类,Scanner类 难点:Class类与Console类,Pattern类与Match类 其他特 ...