【问题标题】:print a newline using tail call optimization使用尾调用优化打印换行符
【发布时间】:2021-04-29 20:40:41
【问题描述】:

在 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 应用了尾调用优化。注意它是如何使用jmp 而不是ret。所以,控制流将是print_newlineprint_charprint_string,回到print_char,回到print_newline的调用者(而不是回到print_newline)。如果没有尾调用优化,print_newline 将变为 mov rdi, 10; call print_char; ret
  • 感谢埃里克!所以没有什么可以“重写”的,这个问题没有意义?
  • (注意它是如何使用jmp 而不是call + ret。)
  • 是的,TCO 已在您发布的代码中应用于print_newline
  • 并不是真正的 TCO 示例,但您也可以将 print_newline: mov rdi, 10 放在紧挨在 print_char: 之前的行上,这样 print_newline 将直接进入 print_char 而无需跳转全部。当然这个技巧只适用一次,例如你也不能这样print_space

标签: assembly nasm tail-call-optimization


【解决方案1】:

为了参考,我也会在这个帖子中提供解决方案。

  1. 没有优化
print_newline:
    mov rdi, 10
    call print_char
    ret
print_char:
    push rdi
    mov rdi, rsp 
    call print_string 
    pop rdi
    ret
  1. 尾调用优化。指令序列call Xret 始终可以替换为jmp X
print_newline:
    mov rdi, 10
    jmp print_char
print_char:
    push rdi
    mov rdi, rsp 
    call print_string 
    pop rdi
    ret
  1. 刚刚落入print_char;基本上是制作一个有两个入口点的子程序。
print_newline:
    mov rdi, 10
print_char:
    push rdi
    mov rdi, rsp 
    call print_string 
    pop rdi
    ret

Here is a more in-depth explanation in my blog

【讨论】:

  • "指令序列call Xret 总是可以用jmp X 代替。"如果 X 函数使用例如 retn 2 从堆栈中弹出某些内容,则并非严格如此。
  • 你是对的,当ret有一个参数时这是不适用的。
  • 为了参考,我也会在这个帖子中提供解决方案。 - 如果这是另一个问答的副本,通常最好关闭一个作为副本另一个。或者,如果问题的差异足以证明相似但不同的答案是合理的,IMO 最好将另一个问题(或您的答案)联系起来,该问题对同一主题有不同的说法。我想这些例子并不真正属于printing a signed integer optimization,但你的答案可以链接到这里以及你的博客。
猜你喜欢
  • 2021-12-16
  • 1970-01-01
  • 2011-03-31
  • 2014-04-06
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 2020-10-21
  • 2010-10-23
相关资源
最近更新 更多