I am trying to use the C function int sprintf(char *str, const char *format, ...)
from NASM on 64-bit Linux. However, no matter how I try to make it work, I end up with a segmentation fault!
Here is my assembly function:
global sprintf_attempt
extern sprintf
section .text
sprintf_attempt:
mov rdx, rdi
xor rax, rax
mov rdi, output_buff
mov rsi, busStringFormat
call sprintf
; should return a pointer to the beginning of the string output_buff
mov rax, output_buff
ret
section .data
busStringFormat: db "%ll is a wonderful number.", 10, 0
section .bss
; make buffer really big so I know that's not the problem
output_buff: resb 5000
To test this function out, I call it from C like so:
#include <inttypes.h>
#include <stdio.h>
char* sprintf_attempt(int64_t);
int main(void) {
printf("%s", sprintf_attempt((int64_t)22));
return 0;
}
All good so far; finally I attempt to assemble, link, compile and run the code, getting a segmentation fault:
alex@home:~/Code/asm_fun$ nasm -felf64 sprintf_attempt.asm \
> && gcc sprintf_attempt.o sprintf_attempt.c -no-pie -std=c99 \
> && ./a.out
Segmentation fault (core dumped)
:o Of course, I loaded the program into GDB to see what might be going wrong. Everything looks fine up until we call sprintf - all the registers have the values I'd expect, anyway. The problem also does not appear to be that output_buff
is not writable. I can write to it manually via eg mov BYTE [output_buff], '*'
(and so on), just fine.
I really am quite a newbie when it comes to assembly, so I'm sure I've misunderstood something obvious. Thanks for your time!
PS: I did see the question at Calling sprintf in x64 assembly, however there is no answer and the comments were not particularly helpful for me (maybe they are but I simply lack the knowledge to grok their wisdom)