问题描述
伊戈尔·日尔科夫 (Igor Zhirkov) 的书Low-Level Programming 中有这个未解决的问题:
"尝试在不调用print_char或复制其代码的情况下重写print_newline。提示:阅读 关于尾调用优化。”。
我花了一些时间阅读有关尾调用优化的文章,但我不知道正确的做法是什么。
原始代码(无尾调用):print_newline => print_char => print_string=>string_length=>print_string
string_length:
xor rax,rax
.loop:
cmp byte [rdi+rax],0 ; if rdi = 0 (not an address),then seg fault
je .end
inc rax
jmp .loop
.end:
ret
print_string:
push rdi
call string_length
pop rsi
mov rdx,rax
mov rax,1
mov rdi,1
syscall
ret
print_char:
push rdi
mov rdi,rsp
call print_string
pop rdi
ret
print_newline:
mov rdi,10
jmp print_char
什么是尾调用优化?
解决方法
为了参考,我也会在这个线程中提供解决方案。
- 没有优化
print_newline:
mov rdi,10
call print_char
ret
print_char:
push rdi
mov rdi,rsp
call print_string
pop rdi
ret
- 尾调用优化。指令序列
call X
和ret
总是可以用jmp X
代替。
print_newline:
mov rdi,10
jmp print_char
print_char:
push rdi
mov rdi,rsp
call print_string
pop rdi
ret
- 刚刚陷入
print_char
;基本上是创建一个带有两个入口点的子程序。
print_newline:
mov rdi,10
print_char:
push rdi
mov rdi,rsp
call print_string
pop rdi
ret