Reputation: 15
The following is a program from a book (Introduction to 64 Bit Intel Assembly Language Programming for Linux, by Seyfarth, 2012), chap 9. The fault (in gdb) is:
Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7aa10a5 in __printf_size (fp=0x400400, info=0x0, args=) at printf_size.c:199 199 printf_size.c: No such file or directory.
Until this chapter, I successfully used the following to "produce an object file", as recommended,
yasm -f elf64 -g dwarf2 -l exit.lst exit.asm
and then,
ld -o prgm prgm.o
This is the program as copied from the book(l 10 push rbp; I had firstly rem'd the ; but had the same result):
segment .text
global main
extern printf
; void print_max ( long a, long b )
; {
a equ 0
b equ 8
print_max:
push rbp; ;normal stack frame
mov rbp, rsp
; leave space for a, b and max
sub rsp, 32
; int max;
max equ 16
mov [rsp+a], rdi ; save a
mov [rsp+b], rsi ; save b
; max = a;
mov [rsp+max], rdi
; if ( b > max ) max = b;
cmp rsi, rdi
jng skip
mov [rsp+max], rsi
skip:
; printf ( "max(%1d,%1d ) = %1d\n",
; a, b, max );
segment .data
fmt db 'max(%1d,%1d) = %1d',0xa,0
segment .text
lea rdi, [fmt]
mov rsi, [rsp+a]
mov rdx, [rsp+b]
mov rcx, [rsp+max]
call printf
; }
leave
ret
main:
push rbp
mov rbp, rsp
; print_max ( 100, 200 );
mov rdi, 100 ;first parameter
mov rsi, 200 ;second parameter
call print_max
xor eax, eax ;to return 0
leave
ret
After a similar segmentation fault with a previous program in this chap ("Hello World" example), I used
gcc -o prgm prgm.o
which had worked until this program.
Upvotes: 1
Views: 5181
Reputation: 11
Gunner gave an excellent summary. The program should have placed a 0 in rax. This can be done using "xor eax, eax" which is the normal way to zero out a register in x86-64 mode. The top half of the register is zeroed out with xor with a 32 bit register and the lower half depends on the the bits of the 2 registers used (with eax, eax the result is 0).
Upvotes: 0
Reputation: 5884
using gcc to link is the easiest way to go if you are going to use functions from the C Library, since gcc takes care of a few things for you "behind the scenes".
To use just ld
, you need to link against ld-linux-x86-64.so.2 and pass it -lc
to link to the C Library.
Next, you are using printf
wrong. If you are not using floating point registers (which you are not) you need to "zero out" rax
.
Also, since you are linking against the C Library, you cannot just ret
from the main
but call exit
.
lea rdi, [fmt]
mov rsi, [rsp+a]
mov rdx, [rsp+b]
mov rcx, [rsp+max]
xor rax, rax ; # of floating point registers used.
call printf
and:
; print_max ( 100, 200 );
mov rdi, 100 ;first parameter
mov rsi, 200 ;second parameter
call print_max
xor eax, eax ;to return 0
leave
xor rdi, rdi
call exit
ld -o $(APP) $(APP).o -lc -I/lib64/ld-linux-x86-64.so.2
and the output:
max(100,200) = 200
Upvotes: 1