是汇编时间了!






4.46/5 (8投票s)
汇编时间
我的同事问我,C/C++ 中是否有类似于 printf
的函数,可以根据格式字符串打印一个包含各种值的数组。 至今还没有找到这样的函数,但难道我们不是开发者吗?
有一个 System V 64 位 ABI 兼容的函数,它接收一个格式 字符串
、参数列表,并将它们传递给 libc 的 sprintf
函数。
不适合工作场合。
下面的代码很危险,绝不应该在生产环境中使用,甚至不要在任何社会基础设施对象附近 50 英里范围内使用。
奇怪的 64 位 ABI 可能会让人头疼:那些可以使用堆栈并让自然规律发挥作用的旧 cdecl 时代都去哪儿了?
.text
.globl lsprintf
.type lsprintf, @function
lsprintf:
# Arguments parsing
# rdi Stores output string address
# rsi Stores format string address
mov %rdx, %rax # list pointer
mov %rcx, %r10 # number of arguments
push %rbx
push %r12
mov %rcx, %rbx # Callee-saved register, we need this
# to clear stack in accordance with cdecl convension
# Let the party start!
cmp $0, %r10
je do_call
cmp $1, %r10
jl do_call
mov 0(%rax), %rdx
add $8, %rax
cmp $2, %r10
jl do_call
mov 0(%rax), %rcx
add $8, %rax
cmp $3, %r10
jl do_call
mov 0(%rax), %r8
add $8, %rax
cmp $4, %r10
jl do_call
mov 0(%rax), %r9
add $8, %rax
cmp $5, %r10
jl do_call
sub $4, %r10 # Do not count arguments saved in registers
mov %rcx, %r11 # We need this rcx register
mov %r10, %rcx
mov %rax, %r12 # We will multiply!
mov $8, %rax
push %rdx
mul %rcx # rax contains number of bytes to the end of arguments list
pop %rdx
add %rax, %r12
sub $8, %r12
mov %r12, %rax
start_loop:
push 0(%rax)
sub $8, %rax
loop start_loop
mov %r11, %rcx
do_call:
mov $0, %rax # Number of floating point arguments passed
call sprintf
cmp $5, %rbx
jl f_end
sub $4, %rbx
mov %rax, %r9
mov %rbx, %rax
mov $8, %rdx
push %rdx
mul %rdx # 64-bit values
pop %rdx
add %rax, %rsp
mov %r9, %rax
f_end:
pop %r12
pop %rbx
ret