0
votes

I am using NASM on linux to write a basic assembly program that calls a function from the C libraries (printf). Unfortunately, I am incurring a segmentation fault while doing so. Commenting out the call to printf allows the program to run without error.

; Build using these commands:
;   nasm -f elf64 -g -F stabs <filename>.asm 
;   gcc <filename>.o -o <filename>
;

SECTION .bss    ; Section containing uninitialized data

SECTION .data   ; Section containing initialized data

  text db "hello world",10 ; 

SECTION .text   ; Section containing code


global main

extern printf

;-------------
;MAIN PROGRAM BEGINS HERE
;-------------

main:



      push rbp

      mov rbp,rsp

      push rbx

      push rsi

      push rdi ;preserve registers

      ****************


      ;code i wish to execute

      push text ;pushing address of text on to the stack
      ;x86-64 uses registers for first 6 args, thus should have been:
      ;mov rdi,text (place address of text in rdi)
      ;mov rax,0 (place a terminating byte at end of rdi)

      call printf ;calling printf from c-libraries

      add rsp,8 ;reseting the stack to pre "push text"

      **************  

      pop rdi ;preserve registers

      pop rsi

      pop rbx

      mov rsp,rbp

      pop rbp

      ret
2
What is the calling convention for library functions, again? My guess is that you used the wrong one.John Dvorak
In the book I am reading (which covers 32 bit assembly, not 64 bit), it simply says to push address of the string, call the function, clean the stack pointer. I thought text would be the only argument needed since printf searches a null byte to terminate.user2177208
The text string must end with a 0 byte! If it doesn't, how will printf() know where it ends?Alexey Frunze
Woops. Thanks Alexey. I forgot to include that in the posted code.user2177208
I don't think you should fix bugs in the code posted in the question. This one, for example, is one possible reason for crashes. Does the code still crash after this fix?Alexey Frunze

2 Answers

3
votes

x86_64 does not use the stack for the first 6 args. You need to load them in the proper registers. Those are:

rdi, rsi, rdx, rcx, r8, r9

The trick I use to remember the first two is to imagine the function is memcpy implemented as rep movsb,

0
votes

You're calling a varargs function -- printf expects a variable number of arguments and you have to account for that in the argument stack. See here: http://www.csee.umbc.edu/portal/help/nasm/sample.shtml#printf1