x31
arm SP寄存器 16byte对齐
调用函数,必须保存当前位置以便函数调用完成后返回,the link register (LR) which is X30,
branch with link (BL) bl 与b 类似,不同的是 bl 在跳转前把下一条指令的地址保存在LR寄存器中,这样bl跳转完成返回后可以从LR寄存器中的地址继续执行。
ret 指令返回并从lr寄存器中继续执行
bl 和 ret 指令 实现了 函数的调用和返回
嵌套函数调用
当bl时,lr寄存器中原来的值怎么处理呢?
嵌套函数调用里,bl之前把lr压入栈中保存,bl会更新lr,调用完成返回后lr值已经没用了,此时把栈中保存的lr值恢复至lr中;
x0-x7,放参数
x0,放返回值
把前面的upper程序改成BL版
main.s
.global _start _start: ldr x0,=instr ldr x1,=outstr bl toupper mov x2,x0 //return code is the length mov x0,1 //stdout ldr x1,=outstr mov x8,64 //linux write system call svc 0 mov x0,0 mov x8,93 svc 0 .data instr: .asciz "a test string , convert To UPPER case.\n" outstr: .fill 255,1,0
upper.s
.global toupper toupper: mov x2,0 loop: ldrb w3,[x0,x2] cmp w3,0 b.eq cout //reach the end of instr cmp w3,'a' b.cc write cmp w3,'z' b.hi write sub w3,w3,'a'-'A' write: strb w3,[x1,x2] add x2,x2,1 //next loop b loop cout: mov x0,x2 ret
makefile:
TARGET=upper ifdef DEBUG DEBUGFLGS = -g else DEBUGFLGS = endif $(TARGET): $(TARGET).o main.o ld -o $@ $^ %.o:%.s as $(DEBUGFLGS) -o $@ $< clean: rm *.o $(TARGET)
用一个栈帧保存3个word
在函数返回之前,应该释放此栈帧: ADD SP, SP, #16
一般用x29做栈帧寄存器
.equ 定义符号,被汇编器替换,只能是数字,功能类似 #define
.macro 开始, .endm 结束;跟c语言#define宏一样;
直接包含某文件,类似 #include