zoukankan      html  css  js  c++  java
  • 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函数的流程

    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地址的值备份到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

  • 相关阅读:
    单片机八位时钟
    共阴数码管断码与位码
    PCB自己做一个原理图模版
    Mongodb在Linux下的安装和启动和配置
    linux下用phpize给PHP动态添加扩展
    微信支付JS各种调试问题
    秒速插入百万测试数据MYSQL,提供你玩玩大数据!
    金子的PHP之禅(函数篇四)
    linux下面查找某个字符或者文件
    金子的PHP之禅(PHP运算符三)
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10023525.html
Copyright © 2011-2022 走看看