2016-11-16 10 views
0
extern puts 
global main 

section .text 
main: 
    mov rax, rdi 
label: 
    test rax, rax 
    je exit 
    push rsi 
    mov rdi, [rsi] 
    call puts 
    pop rsi 
    dec rax 
    add rsi, 8 
    jmp label 
exit: 
    pop rsi 
    ret 

이렇게 nasm 코드를 작성했습니다. 그러나 세분화 오류가 마지막에 발생합니다. 세분화 오류가 발생하는 이유를 이해할 수 없습니다. 당신이 저장해야합니다 (을 puts"오류에 음이 아닌 성공에 번호 또는 EOF"의 경우) 기능의 정수 결과를 반환하는 데 사용됩니다로arg를 사용할 때 nasm segmentation fault가 발생했습니다.

답변

1

rax은 함수 호출에 걸쳐 보존 할 수 보장 할 수 없습니다 puts을 호출하기 전에 rax의 값을 입력하고, 나중에 rsi을 사용하는 것과 같습니다. 나중에 복원하십시오.

0

분명히 64 비트 Linux의 GCC 환경에서 명령 줄 매개 변수를 가져 오려면 Linux 호출 규칙 "System V AMD64 ABI"을 따르는 GCC 호출 규칙에 따라 전달됩니다.

는 이제 C로 프로그램 로직을 번역하자

#include <stdio.h> 

int main (int argc, char** argv) 
{ 
    if (argc != 0) 
    { 
     do 
     { 
      puts (*argv); 
      argc--; 
      argv++; 
     } while (argc); 
    } 
    return; 
} 

ASM은 프로그램이 종료 코드를 반환하지 않습니다. 이 종료 코드는 함수가 반환 될 때 RAX에 있어야합니다. 처음에는 argv 문자열에 프로그램 이름이 들어 있기 때문에 BTW : argc은 항상> 0입니다.

main 함수는 "호출자"(호출자 : puts)와 "호출 수신자"(GCC 환경으로 돌아갑니다)입니다. 호출자는 puts으로 전화하기 전에 RAXRSI을 보존하고 필요할 때 복원해야합니다. 호출 수신자 저장 레지스터는 사용되지 않습니다. 이 작품 (16)

하여 스택을 정렬하는 것을 잊지 마세요 :

extern puts 
global main 

section .text 
main:      ; RDI: argc, RSI: argv, stack is unaligned by 8 
    mov rax, rdi 
label: 
    test rax, rax 
    je exit 
    push rbx    ; Push 8 bytes to align the stack before the call 
    push rax    ; Save it (caller-saved) 
    push rsi    ; Save it (caller-saved) 
    mov rdi, [rsi]   ; Argument for puts 
    call puts 
    pop rsi     ; Restore it 
    pop rax     ; Restore it 
    pop rbx     ; "Unalign" the stack 
    dec rax 
    add rsi, 8 
    jmp label 
exit: 
; pop rsi    ; Once too much 
    xor eax, eax   ; RAX = 0 (return 0) 
    ret      ; RAX: return value