سؤال

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.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top