【问题标题】:printing a signed integer optimization打印有符号整数优化
【发布时间】:2021-04-29 20:54:07
【问题描述】:

在 Igor Zhirkov 的书中Low-Level Programming 中有这个悬而未决的问题:

"尝试在不调用 print_uint、复制其代码或使用 jmp 的情况下重写 print_int。您将 只需要一条指令和仔细的代码放置。

阅读协同程序。”。

“print_int”和“print_uint”提供的代码:

print_uint:
    mov rax, rdi
    mov rdi, rsp
    push 0
    sub rsp, 16
    
    dec rdi
    mov r8, 10

.loop:
    xor rdx, rdx
    div r8
    or  dl, 0x30
    dec rdi       
    mov [rdi], dl
    test rax, rax
    jnz .loop 
   
    call print_string
    
    add rsp, 24
    ret

print_int:
    test rdi, rdi
    jns print_uint
    push rdi
    mov rdi, '-'
    call print_char
    pop rdi
    neg rdi
    jmp print_uint

print_char:
    push rdi
    mov rdi, rsp
    call print_string 
    pop rdi
    ret
print_string:
    push rdi
    call string_length
    pop rsi
    mov rdx, rax
    mov rax, 1
    mov rdi, 1
    syscall
    ret

他所说的那条特殊的单一指令可能是什么?

【问题讨论】:

  • 我看到了摆脱jmp print_uint的方法,但是那个“一条指令”仍然是个谜
  • 您是否应该将print_int 移动到print_uint 之前,以便它可以 进入其中(免费尾调)而不是使用jmp?也许他的意思是“更改一条指令”,如删除jmp print_uint?
  • 顺便说一句,print_uint 写得很好,和我在How do I print an integer in Assembly Level Programming without printf from the c library? 中所做的差不多。但是,如果这不是试图移植到非 Linux,您可以利用 RSP 下面的红色区域,如果您内联系统调用并计算长度,则可以省略sub rsp, 16,而不是调用print_string当你已经知道它在哪里时,让它搜索一个终止的0,因为你推了它。
  • @PeterCordes 谢谢。然而,此代码从未被测试为可能的最快版本,它不是以这种意图编写的。便携性也是没问题的。因为这个作业在本书的早期阶段,读者还不知道红色区域的概念,所以我没有使用它。
  • @IgorZhirkov:是的,与我在我的版本中留下sub rsp 的原因相同(为了人们将其移植到 32 位代码的利益)。如果您实际上是在优化速度,则可以使用乘法逆运算(例如 this code-review Q&A,这将比避免 sub/add 节省更多的周期。:P 另请参阅我的链接答案底部的其他链接,了解一些人们已经尝试过x /= 100 并将其拆分以获得一些 ILP 和其他类似的东西。

标签: assembly x86-64 nasm micro-optimization


【解决方案1】:

很抱歉,很遗憾这是一个错误。

有一对函数print_newlineprint_char,如果之后控制权落到print_charprint_newline可以表示为一条指令。我写了一个blog post about it。基本思想是打印特定字符,即换行符,就像在为其参数分配所述字符的代码时启动“打印任何字符”子例程一样。

print_newline:
   mov rdi, '\n'  ; first integer argument is in rdi
print_char:
   ...

至于print_int,我敢肯定在AMD64上你不能通过一条指令来表达,落到print_uint

【讨论】:

  • 哦!作者本人!谢谢你的回答,谢谢你的好书!
猜你喜欢
  • 2021-05-12
  • 2022-11-11
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
相关资源
最近更新 更多