0

以下是一本书(Introduction to 64 Bit Intel Assembly Language Programming for Linux,Seyfarth,2012 年)第 9 章中的程序。故障(在 gdb 中)是:

程序收到信号 SIGSEGV,分段错误。0x00007ffff7aa10a5 in __printf_size (fp=0x400400, info=0x0, args=) at printf_size.c:199 199 printf_size.c: 没有这样的文件或目录。

直到本章,我成功地使用以下内容“生成目标文件”,如推荐的那样,

yasm -f elf64 -g dwarf2 -l exit.lst exit.asm

进而,

ld -o prgm prgm.o

这是从书中复制的程序(l 10 push rbp; 我首先rem'd ; 但结果相同):

    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

在本章中的前一个程序(“Hello World”示例)发生类似的分段错误之后,我使用了

gcc -o prgm prgm.o

在这个程序之前一直有效。

4

2 回答 2

1

如果您要使用 C 库中的函数,使用 gcc 链接是最简单的方法,因为 gcc 会在“幕后”为您处理一些事情。

要使用 just ld,您需要链接 ld-linux-x86-64.so.2 并将其传递-lc给链接到 C 库。

接下来,你用printf错了。如果您不使用浮点寄存器(您不是),则需要“归零” rax

此外,由于您正在链接 C 库,因此您不能只retmainbut 调用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

和:

;   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

和输出:

最大值(100,200)= 200

于 2014-01-25T01:42:39.457 回答
0

Gunner给出了精彩的总结。该程序应该在 rax 中放置了一个 0。这可以使用“xor eax, eax”来完成,这是在 x86-64 模式下将寄存器归零的正常方法。寄存器的上半部分用 32 位寄存器的 xor 清零,下半部分取决于使用的 2 个寄存器的位(使用 eax,eax 结果为 0)。

于 2014-09-16T22:02:09.670 回答