#include
int main()
{
int a;
a++;
return a;
}
arm-linux-gcc -g stack1.c -o stack1
#include
void func1(int a,int b,int c,int d,int e,int f)
{
int k;
k=e+f;
}
int main()
{
func1(1,2,3,4,5,6);
return 0;
}
#include
void func2(int a,int b)
{
int k;
k=a+b;
}
void func1(int a,int b)
{
int c;
func2(3,4);
c=a+b;
}
int main()
{
func1(1,2);
return 0;
}
init_stack:
ldr sp, =0x54000000
mov pc ,lr
2-初始化BSS段
初始化的全局变量:数据段malloc:堆
未初始化的全局变量:bss段
bss.c
#include
int year;
int main()
{
year = 2017;
return year;
}
arm-linux-gcc bss.c -o bss
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
3-汇编语言跳到c语言运行
跳转有相对跳转和绝对跳转,2.能够更直接地控制处理器 访问MSR MRS CPSR寄存器等。
一、汇编调用C函数假设在start.s中用汇编实现了light_led 标号。
int gboot_main()
{
light_led();
return 0;
}
__asm__(
汇编语句部分
:输出部分 -- 可能修改了c语言中变量的值修改了,这些变量就放在输出部分
:输入部分 -- 可能需要从c语言中拿到一些参数作为汇编的操作数,这些参数就是放在输入部分
:破坏描述部分 -- mov r0,#0 这样把r0原来的值破坏了,所以要放到这个地方来。
);
C内嵌汇编以关键字”__asm__”或”asm”开始,下辖四个部分,各部分之间使用":"分开, 第一部分是必须写的,
4.破坏描述部分: 执行汇编指令会破坏的寄存器描述
void write_p15_c1(unsigned long value)
{
__asm__(
"mcr p15, 0, %0, c1,c0, 0\n"
:
: "r" (value) @编译器选择一个rx寄存器。"r"表示是一个通用寄存器。值从value中来。
);
}
凡是要去读的参数,都是放在输入部分,凡是要是写进去的参数,都是放在输出部分。
unsigned long read_p15_c1(void)
{
unsigned long value;
__asm__(
"mcr p15, 0, %0, c1,c0, 0\n"
: "=r" (value) @ "=" 表示只写操作数,用于输出部。r0中的值要存放到value变量中。
:
: "memory"); //value变量放在栈中的,也就是内存中的值被修改了,通过“memory”通知系统有语句去修改内存。
return value;
}
使用volatile来告诉编译器,不要对接下来的这部分代码进行优化
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");
使用内嵌汇编点亮LED
#define GPKCON 0x7f008800
#define GPKDAT 0x7f008808
int gboot_main()
{
__asm__(
"ldr r1, =0x11110000"
"str r1, [%0]\n"
"ldr r1, =0xa0\n"
"str r1, [%1]\n"
:
:"r" (GPKCON), "r" (GPKDAT)
:"r1"
);
}