2016-10-31 4 views
2

방금 ​​최근에 어셈블리를 시작 했으므로 분명히 초보자입니다. 매우 간단하고 기본적인 프로그램을 작성하고 있었고 방금 이상한 것을 발견했습니다.왜 "rsp"를 가지고 C++ 함수를 호출해야합니까?

진입 점에서 111로 끝나는 테이블의 숫자의 수를 제공하는 프로그램 :

#include <iostream> 
#include <cstdlib> 

extern "C" auto _start(void *, void *)->void; 

auto print_msg(char *msg) { 
    std::cout << msg; 
} 

auto print_int(uint64_t val) { 
    std::cout << val; 
} 

auto main()->int { 
    _start(print_int, print_msg); 
    std::cout << std::endl; 
    system("pause"); 
} 

조립 :

.const 
_tab dw 65535, 61951, 61949, 61925, 61927, 61734, 61735, 61728 
_LENGTH = ($ - _tab)/2 
_msg_1 db 'There are ', 0 
_msg_2 db ' numbers ending with 111 in binary!', 0 

.code 
_start proc 
     push  r15 
     push  r14 
     sub  rsp, 32 + 16 
     mov  r14, rcx 
     mov  r15, rdx 
     xor  rcx, rcx 
     xor  r9, r9 
     lea  r8, _tab 
_LOOP: movzx rax, word ptr [r8] 
     and  rax, 111b 
     cmp  rax, 111b 
     jz  _INC 
     jmp  _END_IF 
_INC: inc  rcx 
_END_IF: inc  r9 
     add  r8, 2 
     cmp  r9, _LENGTH 
     jne  _LOOP 
     mov  [rsp + 32], rcx 
     lea  rcx, _msg_1 
     call  r15 
     mov  rcx, [rsp + 32] 

     sub  rsp, 8 
     call  r14 
     add  rsp, 8 

     lea  rcx, _msg_2 
     call  r15 
     add  rsp, 32 + 16 
     pop  r14 
     pop  r15 
     ret 
_start endp 

end 

내가 언급하는 경우 " sub rsp, 8 "및"rsp, 8 "을"call r14 "주위에 추가하면 프로그램이 즉시 중단됩니다. "mov rspx32", "rcx"및 "mov rcx, rspx32"를 "push rcx"및 "rcx"로 바꾸면 왜 그런지 알기를 바랍니다. 팝 rcx ", 출력됩니다 쓰레기, 나는 또한 그것에 대해 궁금해.

+1

함수 '_start'를 호출하지 마십시오. 그것이 진입 점의 기본 이름입니다 (적어도 Linux에서는). 자신의'_start'를 정의하는 프로그램은 표준 CRT 시작 코드를 연결하지 않으며'_start'는 반환 할 수있는 함수조차도 아닙니다. 그것은 단지 진입 점입니다. TL : DR :'_start'는 많은 독자를위한 혼란스러운 함수 이름입니다. –

답변

4

Windows x86-64 호출 규칙은 CALL 명령 전에 RSP의 16B 정렬이 필요합니다. 이것은 함수 호출을 중심으로 sub rsp,8을 설명합니다.

또한 호출 된 함수의 사용을 위해 예약 된 32B의 음영 공간이 필요하며 이는 sub rsp, 32 + 16의 작업입니다.

기능 항목에 sub rsp, 32 + 16 + 8을 결합한 다음 현시까지 RSP를 사용하지 않는 것이 현명합니다. mov [rsp + 32], rcx에 대해 사용중인 오프셋을 변경할 수도 있습니다. 중요한지 확실하지 않습니다. 질문이 스택 정렬/사용법 이었기 때문에 전체 코드를 읽으려고하지 않았습니다.

호출 된 함수가 음영 공간을 사용하는 이유는 데이터가 음영 공간에 있기 때문에 CALL을 밀거나 팝하는 경우 왜 왜곡 된 출력이 나오는 이유입니다.


컨벤션 링크를 호출/ABI에 대한 태그 위키를 참조하십시오.