以下是一本书中的程序(Seyfarth的64位英特尔汇编语言程序设计简介,2012),第9章。故障(在gdb中)是:
编程接收信号SIGSEGV,分段故障。 __printf_size中的0x00007ffff7aa10a5(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;我先是先重新编写;但结果相同):
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
直到这个计划才开始工作。
答案 0 :(得分:1)
要仅使用ld
,您需要链接到ld-linux-x86-64.so.2并将其传递给-lc
以链接到C库。
接下来,您使用的是printf
错误。如果你没有使用浮点寄存器(你不是),你需要“归零”rax
。
此外,由于您要链接到C库,因此ret
不能main
,而是致电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
和输出:
max(100,200)= 200
答案 1 :(得分:0)
枪手给出了一个很好的总结。该程序应该在rax中放置0。这可以使用" xor eax,eax"这是在x86-64模式下将寄存器归零的常用方法。寄存器的上半部分用xor和32位寄存器清零,下半部分取决于使用的2个寄存器的位(使用eax,eax结果为0)。