记录零散的基础点,便于查找。
ldr r0, =0x00800050 //伪指令,把0x00800050存放到r0
ldr r0,[r1] //取内存数据,把地址r1的数据存放到r0
sub r0, r1 ,#4 // r0=r1-4
sub r0, r1, r2 // r0=r1-r2
add r0, r1, #4 // r0=r1+4
bl xxx // 1.调到xxx 2.把返回地址保存在lr寄存器中
ldm //读内存写入多个寄存器
stm //把多个寄存器的值写入内存
ldmia sp, {fp,sp,pc} //先读取,后增加栈指针,fp,sp,pc(次处存的是之前lr的值,取出来放到pc中)
//无!号表示取栈后sp不会被修改
stmdb sp!, {fp,ip,lr,pc} //堆栈指针先减,再存,存储顺序为先pc,lr,ip,fp(高编号寄存器存放高地址)
//!号表示sp会指向为寄存器压栈后的地址
pc值=当前地址+8 //流水线原因,执行到当前地址时, 当前地址+4指令正在译码
当前地址+8指令正在读取
地位存放低地址 小端模式
高位存放低地址 大端模式
gcc选项:
-v //打印版本号,显示详细的处理过程-o //指定输出文件名
-E //只预处理,不编译,汇编,链接 预处理文件为.i结尾
gcc -E -o xxx.i xxx.c
-S //只编译,不汇编,链接
gcc -S -o xxx.s xxx.i
-c //编译和汇编,不链接
gcc -c -o xxx.o xxx.s
链接得到可执行文件
gcc -o xxx xxx.o
crt1.o crti.o crtbegin.o crtend.o crtn.o是gcc加入的系统标准启动文件
-lc //链接libc库文件,libc库文件中实现了printf函数
-Llibpath //添加库路径
-Iincludepath //添加头文件路径
-nostdlib //不连接标准库,常用于裸机bootloader,内核等程序
-static //静态链接
ldd xxx //命令查找xxx程序依赖哪些库文件
Makefile:
baidu "gnu make 于凤昌"
% //通配符
$@ //目标文件$< //第一个依赖文件
$^ //所有的依赖文件
.PHONY //假想目标
简单变量和延时变量:
:= //即时变量
= //延时变量
?= //延时变量,如果是第一次定义才起效,如果在前面该变量已定义则忽略这句
+= //附加,是即时变量还是延时变量取决于前面的定义
例子:
==========================
A := $(C) //简单变量 a的值即刻确定
B = $(C) //延时变量 b的值在使用时确定
all:
@echo A = $(A) //加@符号后,输出不会显示命令本身
@echo B = $(B)
C = 123
========输出==============
A=空
B=123
========end===============
函数:
$(foreach var,list,text)
$(filter pattern...,text) //在text中取出符合pattern格式的值
$(filter-out pattern...,text) //在text中取出不符合pattern格式的值
$(wildcard pattern) //pattern定义了文件名的格式,wildcard取出其中存在的文件
$(patsubst pattern,replacement,$(var))
例子:
==========================
A =a b cB = $(foreach f, $(A), $(f).o)
C =a b c d/
D = $(filter %/, $(C))
E = $(filter-out %/, $(C))
files = $(wildcard *.c)
files2 = a.c b.c c.c d.c e.c abc
files3 = $(wildcard $(files2)) //查找files2中真实存在的文件
dep_files = $(patsubst %.c,%.d,$(files2))
all:
@echo B = $(B)
@echo D = $(D)
@echo E = $(E)
@echo files = $(files)
@echo files3 = $(files3)
@echo dep_files = $(dep_files)
=========输出=================
B = a.o b.o c.o
D = d/
E = a b c
files = a.c c.c b.c
files3 = a.c b.c c.c
dep_files = a.d b.d c.d d.d e.d abc
========end==================
支持头文件依赖:
gcc -M c.c //打印出依赖
gcc -M -MF c.d c.d //把依赖写入文件c.d
gcc -c -o c.o c.c -MD -MF c.d //编译c.o,并把依赖写入文件c.d
例子:
============================================
objs = a.o b.o c.o
dep_files := $(patsubst %, .%.d, $(objs))
dep_files := $(wildcard $(dep_files))
test: $(objs)
gcc -o test $^
ifneq ($(dep_files),)
include $(dep_files)
endif
%.o : %.c
gcc -c -o $@ $< -MD -MF .$@.d
clean:
rm *.o test
distclean:
rm $(dep_files)
.PHONY: clean
==============================================
link链接脚本:
SECTIONS {
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents }
}
start: 运行时地址
ldadr: 加载地址,不写时默认为运行时地址
SECTIONS {
.text 0 : { *(.text) }
.rodata : { *(.rodata) }
.data 0x30000000 : AT(0x800)
{
__data_load_addr = LOADADDR(.data);
.= ALIGN(4);
__data_start = .;
*(.data)
__data_end = .;
}
.= ALIGN(4);
__bss_start = .;
.bss : { *(.bss) *(.COMMON) }
__bss_end = .;
}
bss段运行地址为0x30000000
bss段不会存在于elf或bin文件中
在汇编中使用lds文件中定义的变量:
ldr r0,=__bss_start
在C中使用lds文件中定义的变量:
extern int __bss_start //使用类型不重要
volatile unsigned int *start=(volatile unsigned int *)&__bss_start;