2012-10-01 7 views
3

argv[0]을 레지스터에 저장하고 인쇄하고 싶지만 어셈블리 프로그램을 실행할 때 segfault가 표시됩니다.NASM에서 argv [0]를 출력하는 방법은 무엇입니까?

추적 :

$ nasm -f macho -o scriptname.o --prefix _ scriptname.asm 
$ ld -o scriptname scriptname.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie 
$ ./scriptname 
Segmentation fault: 11 

scriptname.asm :

[bits 32] 

section .data 

program: db "Program: %s", 0 

section .text 

global start 
extern printf 
extern exit 

start: 

; skip argc 
add esp, 4 

; ebx := argv[0] 
pop ebx 

push ebx 
push program 
call printf 
add esp, 8 

push 0 
call exit 

사양 :

  • LD 64-134.9
  • NASM 0.98.40
  • 엑스 코드 4.5
  • 01,235,
  • 맥 OS X 10.8.2
  • 맥북 프로 2009
+0

생성 된 바이너리가 32 비트인지 확인 하시겠습니까? – Macmade

+0

64 비트에서 실행되는 경우 호출 규칙은 cdecl이 아니지만 sys V. – Macmade

+0

@Macmade, 정보를 제공해 주셔서 감사합니다! 64 비트 프로그램을 만들고 싶다면이 점을 명심하십시오. 프로그램은 * ld'에'-arch i386'을 지정했기 때문에 x86 만 있어야합니다. 컴퓨터에서 동일한 코드를 빌드하고 실행하려고하면 어떻게됩니까? – mcandre

답변

4

분할 오류는 나쁜 스택 정렬 (misaligned_stack_error)에서 비롯됩니다.
그런 문제가 발생하면 항상 GDB으로 프로그램을 실행 해보십시오. 일반적으로 더 많은 정보를 제공합니다.

그러나 C 라이브러리에서 함수를 호출 할 때 스택을 16 바이트 경계에 정렬해야합니다.
Mac OS X 32 비트 ABI에 대한 요구 사항입니다 (64 비트 ABI의 경우 SYS V 호출 규칙을 사용함).

[bits 32] 

section .data 

    hello db "Program name: %s (%i CLI args)", 10, 0 

section .text 

global start 
extern _exit 
extern _printf 

start: 

    ; Store 'argc' into EAX 
    pop  eax 

    ; Store 'argv' into EBX 
    pop  ebx 

    ; Align stack on a 16 bytes boundary, 
    ; as we'll use C library functions 
    mov  ebp,    esp 
    and  esp,    0xFFFFFFF0 

    ; Stack space for local variables 
    ; A little more space than needed, but that will 
    ; ensure the stack is still aligned 
    sub  esp,    16 

    ; Call 'printf': printf(hello, ebx, eax); 
    mov  dword[ esp ],  hello 
    mov  dword[ esp + 4 ], ebx 
    mov  dword[ esp + 8 ], eax 
    call _printf 

    ; Call 'exit': exit(0); 
    mov  dword[ esp ],  0 
    call _exit 

는 사용하여 컴파일 :

을 그래서 여기

(설명을 그냥 이후) 실행 파일 이름을 인쇄 할 프로그램의 작업 버전뿐만 아니라 CLI 인수의 수입니다

nasm -f macho -o test.o test.asm 
ld -o test test.o -arch i386 -lc -macosx_version_min 10.6 

설명 :

우리는 어떤 REGIST에서 첫 번째 저장소 argcargv ERS : 당신은 당신이 정렬 스택을 유지 가정 start의 시작 부분에 한 번만이 작업을 수행 할 수 있습니다

mov  ebp,    esp 
    and  esp,    0xFFFFFFF0 

:

pop  eax 
    pop  ebx 

을 그리고 그 다음 우리는 16 바이트 경계에 스택을 정렬 지역 변수를위한 공간을 만들 때.

그런 다음 로컬 변수에 필요한 공간 인 을 만들어 스택의 정렬 상태를 유지합니다.
여기서 스택 인수를 3 개만 확보 할 필요가 있지만 스택을 정렬 상태로 유지하기 위해 4를위한 공간을 만듭니다.

mov  dword[ esp ],  hello 
    mov  dword[ esp + 4 ], ebx 
    mov  dword[ esp + 8 ], eax 

그런 다음 단순히 C 라이브러리 함수를 호출, 당신은 OK 수 있습니다 :

sub  esp,    16 

그런 다음 호출에 대해 인수를 준비하기 위해, 그 공간에 값을 이동할 수 있습니다.

참고 유용한 정보는 this answer (x86 Assembly on a Mac)에 있습니다.

+0

이 매크로를 사용하더라도 정렬 오류가 계속 발생합니다. 원래 코드를 다시 작성할 수 있습니까? – mcandre

+0

@ JaggedO'Neill 당신 말이 맞아요. 성능상의 이유가 있습니다. – Macmade

+0

@mcandre 편집을 참조하십시오 :) 이제 작동해야합니다. – Macmade

관련 문제