c和汇编混合编程

来源:互联网 发布:期货软件哪个好 编辑:程序博客网 时间:2024/04/27 03:21

一、栈初始化

是一种具有后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的
后取出。
栈底是第一个进栈的数据所处的位置,栈顶是最后一个进栈的数据所处的
位置


根据SP指针指向的位置,栈可以分为满栈空栈
1. 满栈:当堆栈指针SP总是指向最后压入堆栈的数据

2. 空栈:当堆栈指针SP总是指向下一个将要放入数据的空位置

ARM采用满栈

根据SP指针移动的方向,栈可以分为升栈降栈
1. 升栈:随着数据的入栈,
SP指针从低地址->高地址移动

2. 降栈:随着数据的入栈,
SP指针从高地址->低地址移动

ARM采用降栈!

栈帧(stack frame)
就是一个函数所使用的那部分栈,所有函数的栈帧串起来就组成了一个完整的栈。

栈帧的两个边界分别由fp(r11)sp(r13)来限定



初始化堆栈 

init_stack:
ldr sp, =0x34000000
mov pc ,lr

二、Bss段初始化


clean_bss:
ldr r0, =bss_start //从.lds文件获取
ldr r1, =bss_end
cmp r0, r1
moveq pc, lr


clean_loop:
mov r2, #0
str r2, [r0], #4
cmp r0, r1
bne clean_loop
mov pc, lr


初始化的全局变量: 数据段

局部变量  :栈

malloc   :堆

未初始化的全局变量:  BSS段


#include <stdio.h>


int year;
int test=123;
int main()
{
    int temp=4567;
    year=2019;
    return year;
}


arm-linux-gcc bss.c -o bss
arm-linux-readelf -a bss >dump

cat dump


.......

    76: 0001101c     0 NOTYPE  WEAK   DEFAULT   23 data_start
    77: 000082d8     0 FUNC    GLOBAL DEFAULT  UND abort@@GLIBC_2.4
    78: 000083f4     4 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
    79: 000082fc     0 FUNC    GLOBAL DEFAULT   13 _start
    80: 000082e4     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
    81: 00000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    82: 00000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    83: 00008468     0 FUNC    GLOBAL DEFAULT   14 _fini
    84: 00008474     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
    85: 0001101c     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
    86: 00011028     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start__
    87: 00008480     0 NOTYPE  GLOBAL DEFAULT  ABS __exidx_end
    88: 00011020     0 OBJECT  GLOBAL HIDDEN   23 __dso_handle
    89: 0001102c     4 OBJECT  GLOBAL DEFAULT   24 year
    90: 00011030     0 NOTYPE  GLOBAL DEFAULT  ABS __end__
    91: 000083f8   112 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
    92: 00011030     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_end__
    93: 00011028     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start

    94: 00011030     0 NOTYPE  GLOBAL DEFAULT  ABS _bss_end__
    95: 00011024     4 OBJECT  GLOBAL DEFAULT   23 test
    96: 00011030     0 NOTYPE  GLOBAL DEFAULT  ABS _end
    97: 00011028     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
    98: 00008478     0 NOTYPE  GLOBAL DEFAULT  ABS __exidx_start
    99: 000083b0    68 FUNC    GLOBAL DEFAULT   13 main
   100: 000082b4     0 FUNC    GLOBAL DEFAULT   11 _init

三、汇编调用C函数


main.c

#define GPBCON (volatile unsigned long*)0x56000010#define GPBDAT (volatile unsigned long*)0x56000014int gboot_main(){    *(GPBCON) = 0x15400;    *(GPBDAT) = 0x61F;  //根据汇编得来        return 0;    }/*light_led:ldr r0, =GPBCONldr r1, =0x15400str r1, [r0]ldr r0, =GPBDATldr r1, = 0x61Fstr r1, [r0]mov pc, lr*/


start.S
.text.global _start_start:b resetldr pc, _undifined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq_undifined_instruction: .word undifined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word resetundifined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopirq:nopfiq:nopreset:bl set_svcbl disable_watchdogbl disable_interruptbl disable_mmubl init_clockbl init_sdrambl copy_to_rambl init_stackbl clean_bssldr pc, =gboot_main //调用C的函数@bl light_led  //注释掉原来用到的会变函数set_svc:mrs r0, cpsrbic r0, r0,#0x1forr r0, r0,#0xd3msr cpsr, r0mov pc, lr#define pWTCON 0x53000000disable_watchdog:ldr r0, =pWTCONmov r1, #0x0str r1, [r0]mov pc, lrdisable_interrupt:mvn r1, #0x0ldr r0, =0x4a000008str r1, [r0]mov pc, lrdisable_mmu:mcr p15,0,r0,c7,c7,0mrc p15,0,r0,c1,c0,0bic r0, r0, #0x00000007mcr p15,0,r0,c1,c0,0mov pc, lr#define CLKDIVN 0x4c000014#define MPLLCON 0x4c000008#define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0))init_clock:ldr r0, =CLKDIVNmov r1, #0x5str r1, [r0]mcr p15,0,r0,c1,c0,0orr r0,r0,#0xc0000000mcr p15,0,r0,c1,c0,0ldr r0, =MPLLCONldr r1, =MPLL_405MHZstr r1, [r0]mov pc, lr#define mem_contrl 0x48000000init_sdram:ldr r0, =mem_contrl add r3, r0, #4*13adrl r1, mem_data0:ldr r2, [r1], #4str r2, [r0], #4cmp r0, r3bne 0bmov pc, lrcopy_to_ram:ldr r0, =0x0ldr r1, =0x30008000add r3, r0, #1024*4copy_loop:ldr r2, [r0], #4str r2, [r1], #4cmp r0, r3bne copy_loopmov pc, lrinit_stack:ldr sp, =0x34000000mov pc ,lrclean_bss:ldr r0, =bss_startldr r1, =bss_endcmp r0, r1moveq pc, lrclean_loop:mov r2, #0str r2, [r0], #4cmp r0, r1bne clean_loopmov pc, lrmem_data:.long 0x22000000 .long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00018001.long 0x00018001.long 0x008c04f5.long 0x000000b1.long 0x00000030.long 0x00000030#define GPBCON 0x56000010#define GPBDAT 0x56000014light_led:ldr r0, =GPBCONmov r1, #0x400str r1, [r0]ldr r0, =GPBDATmov r1, #0x0str r1, [r0]mov pc, lr

四、C调用汇编函数


main.c

#define GPBCON (volatile unsigned long*)0x56000010#define GPBDAT (volatile unsigned long*)0x56000014int gboot_main(){   // *(GPBCON) = 0x15400;   // *(GPBDAT) = 0x61F;    light_led();    return 0;    }/*light_led:ldr r0, =GPBCONldr r1, =0x15400str r1, [r0]ldr r0, =GPBDATldr r1, = 0x61Fstr r1, [r0]mov pc, lr*/


start.S

.text.global _start_start:b resetldr pc, _undifined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq_undifined_instruction: .word undifined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word resetundifined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopirq:nopfiq:nopreset:bl set_svcbl disable_watchdogbl disable_interruptbl disable_mmubl init_clockbl init_sdrambl copy_to_rambl init_stackbl clean_bssldr pc, =gboot_main@bl light_ledset_svc:mrs r0, cpsrbic r0, r0,#0x1forr r0, r0,#0xd3msr cpsr, r0mov pc, lr#define pWTCON 0x53000000disable_watchdog:ldr r0, =pWTCONmov r1, #0x0str r1, [r0]mov pc, lrdisable_interrupt:mvn r1, #0x0ldr r0, =0x4a000008str r1, [r0]mov pc, lrdisable_mmu:mcr p15,0,r0,c7,c7,0mrc p15,0,r0,c1,c0,0bic r0, r0, #0x00000007mcr p15,0,r0,c1,c0,0mov pc, lr#define CLKDIVN 0x4c000014#define MPLLCON 0x4c000008#define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0))init_clock:ldr r0, =CLKDIVNmov r1, #0x5str r1, [r0]mcr p15,0,r0,c1,c0,0orr r0,r0,#0xc0000000mcr p15,0,r0,c1,c0,0ldr r0, =MPLLCONldr r1, =MPLL_405MHZstr r1, [r0]mov pc, lr#define mem_contrl 0x48000000init_sdram:ldr r0, =mem_contrl add r3, r0, #4*13adrl r1, mem_data0:ldr r2, [r1], #4str r2, [r0], #4cmp r0, r3bne 0bmov pc, lrcopy_to_ram:ldr r0, =0x0ldr r1, =0x30008000add r3, r0, #1024*4copy_loop:ldr r2, [r0], #4str r2, [r1], #4cmp r0, r3bne copy_loopmov pc, lrinit_stack:ldr sp, =0x34000000mov pc ,lrclean_bss:ldr r0, =bss_startldr r1, =bss_endcmp r0, r1moveq pc, lrclean_loop:mov r2, #0str r2, [r0], #4cmp r0, r1bne clean_loopmov pc, lrmem_data:.long 0x22000000 .long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00018001.long 0x00018001.long 0x008c04f5.long 0x000000b1.long 0x00000030.long 0x00000030#define GPBCON 0x56000010#define GPBDAT 0x56000014.global light_ledlight_led:ldr r0, =GPBCONmov r1, #0x400str r1, [r0]ldr r0, =GPBDATmov r1, #0x0str r1, [r0]mov pc, lr


五、C内嵌汇编

C内嵌汇编-格式 

__asm__(
汇编语句部分
:输出部分
:输入部分
:破坏描述部分
);
C
内嵌汇编以关键字”__asm__””asm”开始,下辖四个部分,各部分之间使用":"分开,第一部分是必须写的,后面三部分是可以省略,但是分号:不能省略

1.汇编语句部分:汇编语句的集合,可以包含多条汇编语句,每条语句之间需要使用换行符“\n”隔开或使用分号“ ; ”隔开。
2.输出部分:在汇编中被修改的C变量列表
3.输入部分:作为参数输入到汇编中的变量列表
4.破坏描述部分:执行汇编指令会破坏的寄存器描述

void write_p15_c1 (unsigned long value)
{
__asm__(
“mcr p15, 0, %0, c1, c0, 0\n”
:
: “r” (value) @编译器选择一个R*寄存器
: "memory");
}


unsigned long read_p15_c1 (void)
{
unsigned long value;
__asm__(
“mrc p15, 0, %0, c1, c0, 0\n”
: “=r” (value)@ ’=‘表示只写操作数,用于输出部
:
: "memory");
return value;
}


unsigned long old;
unsigned long temp;
__asm__
volatile(
"mrs %0, cpsr \n"

"orr %1, %0, #128 \n“
"msr cpsr_c, %1\n"
: "=r“ (old), "=r“ (temp)

:"memory") ;


使用volatile来告诉编译器,不要对接下来的这部分代码进行优化 。

main.c
#define GPBCON 0x56000010#define GPBDAT 0x56000014int gboot_main(){   // *(GPBCON) = 0x15400;   // *(GPBDAT) = 0x61F;    //light_led();__asm__("ldr r1, =0x400\n""str r1, [%0]\n""ldr r1, = 0x0\n""str r1, [%1]\n"::"r"(GPBCON),"r"(GPBDAT):"r1");    return 0;    }/*#define GPBCON 0x56000010#define GPBDAT 0x56000014light_led:ldr r0, =GPBCONldr r1, =0x15400str r1, [r0]ldr r0, =GPBDATldr r1, = 0x61Fstr r1, [r0]mov pc, lr*/

start.S
.text.global _start_start:b resetldr pc, _undifined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq_undifined_instruction: .word undifined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word resetundifined_instruction:nopsoftware_interrupt:nopprefetch_abort:nopdata_abort:nopnot_used:nopirq:nopfiq:nopreset:bl set_svcbl disable_watchdogbl disable_interruptbl disable_mmubl init_clockbl init_sdrambl copy_to_rambl init_stackbl clean_bssldr pc, =gboot_main  //调用C的函数set_svc:mrs r0, cpsrbic r0, r0,#0x1forr r0, r0,#0xd3msr cpsr, r0mov pc, lr#define pWTCON 0x53000000disable_watchdog:ldr r0, =pWTCONmov r1, #0x0str r1, [r0]mov pc, lrdisable_interrupt:mvn r1, #0x0ldr r0, =0x4a000008str r1, [r0]mov pc, lrdisable_mmu:mcr p15,0,r0,c7,c7,0mrc p15,0,r0,c1,c0,0bic r0, r0, #0x00000007mcr p15,0,r0,c1,c0,0mov pc, lr#define CLKDIVN 0x4c000014#define MPLLCON 0x4c000008#define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0))init_clock:ldr r0, =CLKDIVNmov r1, #0x5str r1, [r0]mcr p15,0,r0,c1,c0,0orr r0,r0,#0xc0000000mcr p15,0,r0,c1,c0,0ldr r0, =MPLLCONldr r1, =MPLL_405MHZstr r1, [r0]mov pc, lr#define mem_contrl 0x48000000init_sdram:ldr r0, =mem_contrl add r3, r0, #4*13adrl r1, mem_data0:ldr r2, [r1], #4str r2, [r0], #4cmp r0, r3bne 0bmov pc, lrcopy_to_ram:ldr r0, =0x0ldr r1, =0x30008000add r3, r0, #1024*4copy_loop:ldr r2, [r0], #4str r2, [r1], #4cmp r0, r3bne copy_loopmov pc, lrinit_stack:ldr sp, =0x34000000mov pc ,lrclean_bss:ldr r0, =bss_startldr r1, =bss_endcmp r0, r1moveq pc, lrclean_loop:mov r2, #0str r2, [r0], #4cmp r0, r1bne clean_loopmov pc, lrmem_data:.long 0x22000000 .long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00000700.long 0x00018001.long 0x00018001.long 0x008c04f5.long 0x000000b1.long 0x00000030.long 0x00000030