2012-07-14 3 views
2

어셈블리 언어로 간단한 프로그램을 작성하여 64 비트 Ubuntu OS에서 실행하려고합니다. 그러나 "세그먼트 오류 (코어 덤프) 오류"에 실패했습니다. 코드에서 여러 문제가 있습니다AT & T 어셈블리 코드의 세그먼트 오류 (코어 덤프) 오류

.section .data 
    values : 
     .int 10, 15, 20, 25, 30 ,35, 40, 45, 50, 55, 60 
    output : 
     .asciz "The value is %d\n" 
    .section .text 
    .globl main 
    main : 
     nop 
     movl $0, %edi 
    loop : 
     movl values(, %edi, 4), %eax 
     pushq %rax 
     pushq $output 
     call printf 
     addl $8, %esp 
     inc %edi 
     cmpl $11, %edi 
     jne loop 
     movl $0, %ebx 
     movl $1, %eax 
     int $0x80 
+0

당신의'e__' 레지스터의 대부분은'r__'이어야한다고 생각합니다. 이것은 x86 어셈블리로 작성되었으며 모든 필요한 변경을하지 않고 강제로 x64로 이식 된 것 같습니다. – Mysticial

+0

나는 그것을 시도했지만 작동하지 않습니다. – Nmzzz

+1

64 비트로 조립 되었습니까? 그럼 스택은 DWORD가 아니라 QWORD가 맞춰 졌기 때문에 rsp에 8을 더하는 것은 잘못되었습니다. printf 호출 후 rsp에 16을 더해야합니다 – Gunner

답변

3

:

여기 내 코드입니다.

64bit Ubuntupushq %rax 나는 당신이 64 비트 실행 파일을 만들려고한다고 추측합니다.

그 다음, 그렇다면 ... 여기

:

pushq %rax 
pushq $output 
call printf 
addl $8, %esp 

가 제대로 함수 호출 후 스택을 균형 아닙니다. 이것이 여전히 64 비트 코드라는 것을 기억하십니까? rsp에 추가해야합니다 (esp이 아님). 또한 2 개의 8 바이트 매개 변수를 푸시하는 경우 정확히 2 개의 8 바이트 매개 변수를 제거해야합니다. 즉 8을 추가하지 말고 16을 추가해야합니다.

그러나 그보다 더 나쁩니다. 64 비트 모드에서는 매개 변수가 다르게 전달됩니다. 제 1 파라미터는 레지스터 (rdi, rsi, rdx, rcx, r8r9)에있다. 그래서, 우리를 제공합니다 : 여기

movq %rax, %rsi 
movq $output, %rdi 
movq $0, %rax ; number of vector registers used for var-arg-function printf() 
call printf 

:

inc %edi 

당신은 바로 호출 및 매개 변수 전달이 레지스터를 사용하여 rdi의 가치를 파괴했다. 전화하기 전에 수동으로 rdi을 누른 다음 다시 팝업해야합니다. 또는 전역 변수에 저장할 수 있습니다. 밀어 넣기 및 팝하기를 선택하는 경우 스택 포인터 rsp이 항상 call 명령보다 먼저 16 바이트 정렬되어 있는지 확인하십시오. 여기

:

movl $0, %ebx 
movl $1, %eax 
int $0x80 

32 비트 시스템 호출 인터페이스를 사용하고 있습니다. 64 비트 프로그램에서 당신은 64 비트 시스템 호출 인터페이스를 사용해야합니다 : 이제

movq $60, %rax ; sys_exit 
movq $0, rdi ; return 0 (success) 
syscall 

을, 나는이 일이 너무 문제가있을 수 있습니다 생각 :

일반적으로
movl $0, %edi 
loop : 
movl values(, %edi, 4), %eax 

, 당신은 안 64 비트 코드의 주소 계산에 32 비트 레지스터 및 32 비트 명령어 사용 나는로 변경 것 : 두 작품 중 어느 것도 values의 주소가 2GB 이하 더 rip (멀리 있기 때문에 경우

movl $0, %rdi 
loop : 
movl values(, %rdi, 4), %eax 

사실 : 변위는 대부분의 지시에 메모리 피연산자에 부호있는 32 비트 정수로 제한됩니다 64 비트 모드에서는 대다수가 64 비트 모드에서 변위 메모리 연산 코드를 사용하지 않고 rip- 상대 주소 지정을 사용하는 경우), 수동으로 64 비트 주소 values과 색인을 수동으로 추가해야합니다. 배열에 4를 곱합니다. 도중에 잘라내기를하지 않고 64 비트 추가를 수행해야합니다.

는해야 하 읽

  • 시스템 V 응용 프로그램 바이너리 인터페이스 AMD64 아키텍처 프로세서 보충 초안 버전

Agner 안개 다른 C++ 컴파일러에 대한 규칙과 운영 체제를 호출 0.99.6

  • +0

    당신은 너무 친절합니다. 고맙습니다. 필자는 코드 샘플이 모두 32 비트 OS로 작성된 PROFESSIONAL ASSEMBLY LANGUAGE라는 책을 읽었으므로 64 비트 OS에서 테스트했을 때 많은 문제가 발생했습니다. 다시 감사합니다! – Nmzzz

    관련 문제