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