I tried the following code and it ends up with 68 lines of native instructions. Thatâs very good compared to the 500+ instructions that the original blog claimed.
@code_native Formatting.printfmt("{1:>4s} {2:.2f}", "abc", 12)
I donât quite understand, however, why it could be so much simpler in C. I just copied the instructions from that blog below. It almost seems that the it does nothing except calling another function (see the jmp
instruction at the end).
f:
.LFB23:
.cfi_startproc
movq %rsi, %r8
movl $.LC0, %ecx
movq $-1, %rdx
movl $1, %esi
movl $1, %eax
jmp __sprintf_chk
.cfi_endproc
I have reproduced this on my mac. It turns into 21 lines of instructions:
$ cat test.c
#include <stdio.h>
void f(char *buffer, const char *a, double b) {
sprintf(buffer, "this is a %s %g", a, b);
}
$ gcc -g -c -o test.o test.c
$ objdump -d -S test.o
test.o: file format Mach-O 64-bit x86-64
Disassembly of section __TEXT,__text:
_f:
; void f(char *buffer, const char *a, double b) {
0: 55 pushq %rbp
1: 48 89 e5 movq %rsp, %rbp
4: 48 83 ec 20 subq $32, %rsp
8: 31 c0 xorl %eax, %eax
a: 48 8d 0d 33 00 00 00 leaq 51(%rip), %rcx
11: 48 c7 c2 ff ff ff ff movq $-1, %rdx
18: 48 89 7d f8 movq %rdi, -8(%rbp)
1c: 48 89 75 f0 movq %rsi, -16(%rbp)
20: f2 0f 11 45 e8 movsd %xmm0, -24(%rbp)
; sprintf(buffer, "this is a %s %g", a, b);
25: 48 8b 7d f8 movq -8(%rbp), %rdi
29: 4c 8b 45 f0 movq -16(%rbp), %r8
2d: f2 0f 10 45 e8 movsd -24(%rbp), %xmm0
32: 89 c6 movl %eax, %esi
34: b0 01 movb $1, %al
36: e8 00 00 00 00 callq 0 <_f+0x3B>
; }
3b: 89 45 e4 movl %eax, -28(%rbp)
3e: 48 83 c4 20 addq $32, %rsp
42: 5d popq %rbp
43: c3 retq
Update: added assembly code compiled from sprintf
C code.