Assembly 打印有符号整数优化
伊戈尔·日尔科夫的书中有一个未回答的问题: 尝试在不调用print_uint、复制其代码或使用jmp的情况下重写print_int。你会 只需要一条指令和仔细的代码放置 阅读有关合作惯例的文章 为print\u int和print\u uint提供的代码:Assembly 打印有符号整数优化,assembly,x86-64,nasm,micro-optimization,Assembly,X86 64,Nasm,Micro Optimization,伊戈尔·日尔科夫的书中有一个未回答的问题: 尝试在不调用print_uint、复制其代码或使用jmp的情况下重写print_int。你会 只需要一条指令和仔细的代码放置 阅读有关合作惯例的文章 为print\u int和print\u uint提供的代码: print_uint: mov rax, rdi mov rdi, rsp push 0 sub rsp, 16 dec rdi mov r8, 10 .loop: xor
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
他说的那个特别的指令可能是什么?我很抱歉,但不幸的是,这是一个错误 有一对函数print_newline和print_char,其中print_newline可以表示为一条指令,如果控件在之后转到print_char。我写了一封信。其基本思想是,打印特定字符(即换行符馈送)就像在为其参数指定所述字符的代码时开始打印任何字符子例程一样
print_newline:
mov rdi, '\n' ; first integer argument is in rdi
print_char:
...
至于打印单元,我确信在AMD64上,您不能通过一条指令来表达它,而转而使用打印单元。非常抱歉,但不幸的是,这是一个错误 有一对函数print_newline和print_char,其中print_newline可以表示为一条指令,如果控件在之后转到print_char。我写了一封信。其基本思想是,打印特定字符(即换行符馈送)就像在为其参数指定所述字符的代码时开始打印任何字符子例程一样
print_newline:
mov rdi, '\n' ; first integer argument is in rdi
print_char:
...
至于print_______________________________________________________________________?也许他的意思是改变一条指令,比如删除jmp打印单元?顺便说一句,打印单元写得很好,和我在中做的差不多。但是,如果这不想移植到非Linux系统,您可以利用RSP下面的红色区域,省去子RSP,16如果您内联系统调用并计算长度,而不是调用print_string并在您已经知道终止0的位置时让它搜索终止0,因为您推了它。@PeterCordes谢谢。然而,这段代码从未被测试为可能的最快版本,并不是出于这个目的编写的。可移植性也是毫无疑问的。因为这项任务在书中很早就出现了,读者还不知道红色区域的概念,所以我没有使用它。@IgorZhirkov:是的,这与我在版本中留下sub-rsp的原因相同,也是为了让人们将其移植到32位代码。如果你真的在优化速度,你会使用一个乘法逆,比如,这将比避免sub/add节省更多的周期P也可以在我的链接答案底部看到一些博客的其他链接,在这些博客中,人们尝试了x/=100,并将其拆分以获得一些ILP,以及其他类似的东西。我看到了摆脱jmp打印单元的方法,但是这一条指令仍然是个谜,你应该在打印之前将打印移到哪个位置,这样它就可以免费使用tailcall而不是使用jmp?也许他的意思是改变一条指令,比如删除jmp打印单元?顺便说一句,打印单元写得很好,和我在中做的差不多。但是,如果这不想移植到非Linux系统,您可以利用RSP下面的红色区域,省去子RSP,16如果您内联系统调用并计算长度,而不是调用print_string并在您已经知道终止0的位置时让它搜索终止0,因为您推了它。@PeterCordes谢谢。然而,这段代码从未被测试为可能的最快版本,并不是出于这个目的编写的。可移植性也是毫无疑问的。因为这项任务在书中很早就出现了,读者还不知道红色区域的概念,所以我没有使用它。@IgorZhirkov:是的,这与我在版本中留下sub-rsp的原因相同,也是为了让人们将其移植到32位代码。如果你真的在优化速度,你会使用一个乘法逆,比如,这将比避免sub/add节省更多的周期P在我的链接答案的底部,也可以看到一些博客的其他链接,在这些博客中,人们尝试了x/=100,并将其拆分以获得一些ILP,以及其他类似的东西。哦!作者本人!谢谢你的回答,也谢谢你那本很棒的书!哦作者本人!谢谢你的回答,也谢谢你那本很棒的书!