c和汇编混合编程
2017-12-14 22:34
134 查看
一、栈初始化
栈是一种具有后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的
后取出。栈底是第一个进栈的数据所处的位置,栈顶是最后一个进栈的数据所处的
位置
根据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
start.S
四、C调用汇编函数
main.c
start.S
五、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
start.S
栈是一种具有后进先出性质的数据组织方式,也就是说后存放的先取出,先存放的
后取出。栈底是第一个进栈的数据所处的位置,栈顶是最后一个进栈的数据所处的
位置
根据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*)0x56000014 int gboot_main() { *(GPBCON) = 0x15400; *(GPBDAT) = 0x61F; //根据汇编得来 return 0; } /*light_led: ldr r0, =GPBCON ldr r1, =0x15400 str r1, [r0] ldr r0, =GPBDAT ldr r1, = 0x61F str r1, [r0] mov pc, lr */
start.S
.text .global _start _start: b reset ldr pc, _undifined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr 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 reset undifined_instruction: nop software_interrupt: nop prefetch_abort: nop data_abort: nop not_used: nop irq: nop fiq: nop reset: bl set_svc bl disable_watchdog bl disable_interrupt bl disable_mmu bl init_clock bl init_sdram bl copy_to_ram bl init_stack bl clean_bss ldr pc, =gboot_main //调用C的函数 @ bl light_led //注释掉原来用到的会变函数 set_svc: mrs r0, cpsr bic r0, r0,#0x1f orr r0, r0,#0xd3 msr cpsr, r0 mov pc, lr #define pWTCON 0x53000000 disable_watchdog: ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] mov pc, lr disable_interrupt: mvn r1, #0x0 ldr r0, =0x4a000008 str r1, [r0] mov pc, lr disable_mmu: mcr p15,0,r0,c7,c7,0 mrc p15,0,r0,c1,c0,0 bic r0, r0, #0x00000007 mcr p15,0,r0,c1,c0,0 mov pc, lr #define CLKDIVN 0x4c000014 #define MPLLCON 0x4c000008 #define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0)) init_clock: ldr r0, =CLKDIVN mov r1, #0x5 str r1, [r0] mcr p15,0,r0,c1,c0,0 orr r0,r0,#0xc0000000 mcr p15,0,r0,c1,c0,0 ldr r0, =MPLLCON ldr r1, =MPLL_405MHZ str r1, [r0] mov pc, lr #define mem_contrl 0x48000000 init_sdram: ldr r0, =mem_contrl add r3, r0, #4*13 adrl r1, mem_data 0: ldr r2, [r1], #4 str r2, [r0], #4 cmp r0, r3 bne 0b mov pc, lr copy_to_ram: ldr r0, =0x0 ldr r1, =0x30008000 add r3, r0, #1024*4 copy_loop: ldr r2, [r0], #4 str r2, [r1], #4 cmp r0, r3 bne copy_loop mov pc, lr init_stack: ldr sp, =0x34000000 mov pc ,lr clean_bss: ldr r0, =bss_start 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 mem_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 light_led: ldr r0, =GPBCON mov r1, #0x400 str r1, [r0] ldr r0, =GPBDAT mov r1, #0x0 str r1, [r0] mov pc, lr
四、C调用汇编函数
main.c
#define GPBCON (volatile unsigned long*)0x56000010 #define GPBDAT (volatile unsigned long*)0x56000014 int gboot_main() { // *(GPBCON) = 0x15400; // *(GPBDAT) = 0x61F; light_led(); return 0; } /*light_led: ldr r0, =GPBCON ldr r1, =0x15400 str r1, [r0] ldr r0, =GPBDAT ldr r1, = 0x61F str r1, [r0] mov pc, lr */
start.S
.text .global _start _start: b reset ldr pc, _undifined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr 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 reset undifined_instruction: nop software_interrupt: nop prefetch_abort: nop data_abort: nop not_used: nop irq: nop fiq: nop reset: bl set_svc bl disable_watchdog bl disable_interrupt bl disable_mmu bl init_clock bl init_sdram bl copy_to_ram bl init_stack bl clean_bss ldr pc, =gboot_main @ bl light_led set_svc: mrs r0, cpsr bic r0, r0,#0x1f orr r0, r0,#0xd3 msr cpsr, r0 mov pc, lr #define pWTCON 0x53000000 disable_watchdog: ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] mov pc, lr disable_interrupt: mvn r1, #0x0 ldr r0, =0x4a000008 str r1, [r0] mov pc, lr disable_mmu: mcr p15,0,r0,c7,c7,0 mrc p15,0,r0,c1,c0,0 bic r0, r0, #0x00000007 mcr p15,0,r0,c1,c0,0 mov pc, lr #define CLKDIVN 0x4c000014 #define MPLLCON 0x4c000008 #define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0)) init_clock: ldr r0, =CLKDIVN mov r1, #0x5 str r1, [r0] mcr p15,0,r0,c1,c0,0 orr r0,r0,#0xc0000000 mcr p15,0,r0,c1,c0,0 ldr r0, =MPLLCON ldr r1, =MPLL_405MHZ str r1, [r0] mov pc, lr #define mem_contrl 0x48000000 init_sdram: ldr r0, =mem_contrl add r3, r0, #4*13 adrl r1, mem_data 0: ldr r2, [r1], #4 str r2, [r0], #4 cmp r0, r3 bne 0b mov pc, lr copy_to_ram: ldr r0, =0x0 ldr r1, =0x30008000 add r3, r0, #1024*4 copy_loop: ldr r2, [r0], #4 str r2, [r1], #4 cmp r0, r3 bne copy_loop mov pc, lr init_stack: ldr sp, =0x34000000 mov pc ,lr clean_bss: ldr r0, =bss_start 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 mem_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_led light_led: ldr r0, =GPBCON mov r1, #0x400 str r1, [r0] ldr r0, =GPBDAT mov r1, #0x0 str 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 0x56000014 int 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 0x56000014 light_led: ldr r0, =GPBCON ldr r1, =0x15400 str r1, [r0] ldr r0, =GPBDAT ldr r1, = 0x61F str r1, [r0] mov pc, lr */
start.S
.text .global _start _start: b reset ldr pc, _undifined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr 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 reset undifined_instruction: nop software_interrupt: nop prefetch_abort: nop data_abort: nop not_used: nop irq: nop fiq: nop reset: bl set_svc bl disable_watchdog bl disable_interrupt bl disable_mmu bl init_clock bl init_sdram bl copy_to_ram bl init_stack bl clean_bss ldr pc, =gboot_main //调用C的函数 set_svc: mrs r0, cpsr bic r0, r0,#0x1f orr r0, r0,#0xd3 msr cpsr, r0 mov pc, lr #define pWTCON 0x53000000 disable_watchdog: ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] mov pc, lr disable_interrupt: mvn r1, #0x0 ldr r0, =0x4a000008 str r1, [r0] mov pc, lr disable_mmu: mcr p15,0,r0,c7,c7,0 mrc p15,0,r0,c1,c0,0 bic r0, r0, #0x00000007 mcr p15,0,r0,c1,c0,0 mov pc, lr #define CLKDIVN 0x4c000014 #define MPLLCON 0x4c000008 #define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0)) init_clock: ldr r0, =CLKDIVN mov r1, #0x5 str r1, [r0] mcr p15,0,r0,c1,c0,0 orr r0,r0,#0xc0000000 mcr p15,0,r0,c1,c0,0 ldr r0, =MPLLCON ldr r1, =MPLL_405MHZ str r1, [r0] mov pc, lr #define mem_contrl 0x48000000 init_sdram: ldr r0, =mem_contrl add r3, r0, #4*13 adrl r1, mem_data 0: ldr r2, [r1], #4 str r2, [r0], #4 cmp r0, r3 bne 0b mov pc, lr copy_to_ram: ldr r0, =0x0 ldr r1, =0x30008000 add r3, r0, #1024*4 copy_loop: ldr r2, [r0], #4 str r2, [r1], #4 cmp r0, r3 bne copy_loop mov pc, lr init_stack: ldr sp, =0x34000000 mov pc ,lr clean_bss: ldr r0, =bss_start 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 mem_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
相关文章推荐
- C/汇编的混合编程
- 嵌入式Linux入门基础知识 ---- 链接脚本、汇编语言、混合编程
- CCS下的C和汇编的混合编程
- 如何在64位的linux系统上使用汇编和C语言混合编程-32汇编移植64位系统
- c/汇编的混合编程
- VxWorks中高精度实时时钟的实现及C语言汇编混合编程
- C和汇编混合编程
- C++与汇编的混合编程
- 汇编与C的混合编程(数字振荡器的实现)
- tiny6410裸机实验第1章--------------ARM汇编和编程基础(C与ARM汇编混合编程)
- C与汇编混合编程
- C语言与汇编语言混合编程应遵守的规则
- STC15单片机驱动WS2812B七彩LED(汇编混合编程)
- C语言与汇编语言混合编程
- C/C++ 与汇编混合编程 总结
- 关于在ARM中(MDK下)C与汇编混合编程的问题
- C与汇编混合编程
- 汇编与C混合编程(6.19)
- C 和 汇编语言的混合编程(实时控制TLC1549的实现)
- 嵌入式Linux ARM汇编(七)——C语言与ARM汇编混合编程