20230818 CHAPTER 6 Functions and the Stack 函数和栈

发布时间 2023-08-19 01:11:18作者: 杨大茄子

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