Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / assembler

It's Assembler Time!

4.46/5 (8 votes)
8 Jul 2017CC (ASA 3U) 6.3K  
Assembler time

My colleague asked me if there is a printf-like function in C/C++ which would provide him a way of printing an array of various values according to some format line. No function has been found so far, but aren't we DEVELOPERS ourselves?

There's a System V 64-bit ABI compatible function which takes a format string, list of arguments, and passes them into the libc sprintf function.

Not safe for work.
The code below is dangerous and should NEVER be used not only in the production environment, but also not 50 miles closer to any of the social infrastructure objects.

Weird 64-bit ABI may be a headache: where have those old cdecl times gone when we could put everything on stack and let nature do the rest?

ASM
.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

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-Share Alike 3.0 Unported License