2013-03-17 1 views
3

실패 컴파일하고 오류가 발생하지 않습니다 그리고 내가 그것을 실행하려고하면 리눅스 ELF 을 생산 링크 내가 얻을 : 나는 그것의 그것이 안녕하세요이이 경우에도없는보고 왜 잘못된 ELF 파일을 생성 가정링킹 리눅스 x86-64에 조립 LD와 안녕하세요 세계 프로그램은 내가 최근 리눅스에 86 64 비트 어셈블리와 주변 놀겠다는 거 봤는데 겉보기에 간단한 프로그램을 컴파일 한 후 내 머리를 긁적 왼쪽하고

.:[ [email protected] asm ]:. 
#(0)> ./hello 
bash: ./hello: No such file or directory 

. 이것은 쉽게 해결 될 수 있다면 아마, 그것으로 장난 그냥 궁금하겠습니다 why-- 확실하지^_^여기

내 컴파일/링크 명령 줄입니다 : 여기

nasm -f elf64 hello.s -g 
ld -o hello hello.o -lc 

입니다 코드 :

section .data 
    msg: db "Hello, world!",0xa,0 

section .text 
    extern printf 
    global main 

main: 
    push rbp 
    mov rbp, rsp 

    mov rdi, msg 
    xor rax, rax 
    call printf 
    xor rax, rax 

    pop rbp 
    ret 

편집 - 나는

+0

hello.o 주요 -e

LD를 사용 아무 것도 없으면 -lc 플래그를 제거하고 printf의 extern을 주석 처리하면 파일이 작동합니다. – zxcdw

+0

어떻게 생각 하시나요? :) 그럼 printf는 정의되지 않은 심볼입니다 ... – h4unt3r

+0

사실 나는 printf 호출을 주석 처리했습니다.하지만 제가 말하고자하는 것은 파일이 libc에 링크되어 있지 않으면 잘 동작한다는 것입니다. – zxcdw

답변

4

저는 32 비트 하드웨어를 실행 중이며 64 비트 항목을 테스트 할 수 없습니다. 32 비트 코드에서이 "no such file"오류를 보았습니다. ld는 기본적으로 "/lib/ld-linux.so.1"을 사용합니다.이 문자열을 실행 파일의 일반 텍스트로 볼 수 있습니다. 이것은 존재하지 않는 파일입니다 (분명히 "안녕하세요"가 바로 여기 있습니다!). 해결 방법은 ld -I/lib/ld-linux.so.2입니다. 필자는 비슷한 솔루션이 64 비트에서 작동 할 것으로 생각하지만, "인터프리터"또는 "동적 링커"가 무엇인지 알지 못합니다. 실행 파일에서 유사한 문자열을 찾아보고 lib에서 비슷한 .so를 찾습니다. gcc를 사용하려면 "필요"하지 않아야하지만 ... gcc는이 항목을 찾을 위치를 알고 있습니다! 사용하기가 더 쉬울 수도 있습니다. 혼란스러운 오류 지옥이지?

은 (난 당신이 이런 식으로 할 거라면 당신의 엔트리 포인트가 _start하지 main 것으로 기대 당신이에서 ret 할 수 없습니다 -.. SYS_exit 시스템 또는 종료()를 사용)

나는 "기호 테이블 0"에 대한 nrz 오류에 익숙하지 않다. 확실하게 Nasm을 의도적으로 변경하지 않았습니다! Nasm 개발자는 http://www.nasm.us 또는 그 주변에서 기다리고 있으며 피드백과 버그 리포트를 듣고 기뻐할 것입니다. (좋아, 아마도 버그 리포트에 대해 "기쁘지"않다.) 내가 무엇인지 알아낼 수 있는지 알게 될 것이다 ...

FWIW, NAMM은 기본적으로 -g 스위치로 "stabs"디버깅 정보로 설정된다. "난장이"디버깅 정보를 사용하려면 -F dwarf ... 더 잘 작동해야합니다 ...

+0

고마워요! 당신은 완전히 자리를 잡았습니다. – h4unt3r

1

먼저, printf을 사용하려면 gcc와 연결 할 대신할 필요가 GCC :)를 사용하지 않으려는:

gcc -o hello hello.o 

그런 다음 다른 문제가 발생할 수 있습니다. 나는이 방법 YASM로 이동 및 조립을하고 연결하여 그 문제를 해결 한

 
[email protected]:~/code/asm$ nasm -f elf64 hello.asm -g; gcc -o hello hello.o 
/usr/bin/ld: error: relocation section 9 uses unexpected symbol table 0 
collect2: error: ld returned 1 exit status 

: 나는 버그 NASM에서 의도 된 변화인지 확실하지 않다

yasm -f elf64 hello.s -g dwarf2 
gcc -o hello hello.o 

가 어느

./hello 
Hello, world! 
+1

글쎄, 그게 ... 링컨에 gcc를 사용하고 싶지 않다. ld를 사용하고 싶다. 이후 ... – h4unt3r

+0

@ h4unt3r 맞습니다. 문제는 표준 라이브러리가 없다는 것입니다. – stdcall

+0

기호 printf가 stdlib에 있고 그 코드를 내 ld 플래그와 함께 연결했기 때문에 -lc – h4unt3r

1

코드를 조금 수정하십시오.

section .data 
     msg: db "Hello, world!",0xa,0 
section .text 
     extern printf 
     global main 
main: 
     push rbp 
     mov  rbp, rsp 
     mov  rdi,msg 
     xor  rax,rax 
     call printf 
     xor  rax,rax 
     pop  rbp 

     mov  rax,60 ; use exit syscall 
     mov  rdi,0 ; error code 0 
     syscall   ; call kernel 

과 가치가있는 경우 -o 안녕하세요 -lc --dynamic 링커 /lib64/ld-linux-x86-64.so.2

+0

'int 0x80'은 64 비트 코드에서 선호되지 않습니다 (32 비트 코드 호환성이없는 리눅스 커널을 생성 할 수 있습니다). 선호되는 방법은 _SYSCALL_ 명령어를 사용하는 것입니다 (시스템 호출 번호와 전달 방법은'int 0x80 '과 다릅니다). 'main'이 함수이기 때문에 _C_ runtime과 링크하면 _ret_를 사용하는 것이 문제가되지 않습니다. 스택에 함수를 호출하는 _C_ 런타임 함수로 되돌아가는 리턴 주소가 있습니다. –

+0

@MichaelPetch 사용자 입력에 따라 syscall로 수정되었습니다. 감사! – Den