>

조립 코드 초보자입니다. C ++로 개발할 때 MSVC에서 생성 한 일부 어셈블리 코드를 이해하지 못했습니다. 해당 코드는 다음과 같습니다.

00DA1965  push        4 // The number of bytes we want
00DA1967  call        operator new (0DA1339h) // Call to 'new' to allocate memory
00DA196C  add         esp,4 // Add the 4 bytes to the stack pointer
00DA196F  mov         dword ptr [ebp-0D4h],eax // Move the return address from EAX into a temporary variable?
00DA1975  mov         eax,dword ptr [ebp-0D4h] // Move it back into EAX?
00DA197B  mov         dword ptr [age],eax // And then into my variable?

해당 C ++ 코드 :

int *age = new int;

올바로 이해하면 EAX의 값을 EBP-0D4h의 임시 변수로 옮깁니다. 그리고 다음 지시에서 우리는 그것을 원래 위치로 다시 옮깁니다.

이점은 무엇입니까? (00DA196F 및 00DA1975)


  • 답변 # 1

    MSVC의 최적화되지 않은 디버그 빌드 asm 출력은 일반적으로 gcc 또는 clang의 최적화되지 않은 빌드보다 훨씬 더 치명적입니다.

    디버그 빌드에서도 스택에 반환 값을 스필/리로드 할 수있는 확실한 이유가 없습니다.: C ++ 추상 머신의 이름을 통해 임시에 액세스 할 수 없으며 디버그 정보가 없습니다. 그것은 당신이 new 의 끝 사이에 그것을 볼 수 있습니다   p 의 업데이트 .

    int*  는 사소하게 복사 가능한 유형이므로 반환 값을 로컬에 복사 할 때 실행할 복사 생성자가 없습니다. 그러나 아마도 이것이 MSVC가하는 이유 일 것입니다.

    <시간> gcc는 new 를 넣으면 함수 또는 정적 초기화 프로그램 함수 에서이 작업을 수행하지 않습니다.  세계적인 범위에서. https://godbolt.org/z/51SM3N

    어리석은 브레인 데드 asm을보고 싶지 않으면 -O2 와 같은 최적화를 사용하여 컴파일  또는 -Ox  MSVC에서. 그런 다음 예상되는 정적 초기화 프로그램을 얻습니다.

    ;;; x86 MSVC -O2 output
    ??__Ep@@YAXXZ PROC                                  ; ??__Ep@@YAXXZ, COMDAT
        push    4
        call    void * operator new(unsigned int)                            ; operator new
        add     esp, 4
        mov     DWORD PTR int * p, eax      ; p
        ret     0
    
    

    x86-64 또는

    ?__Ep@@YAXXZ PROC                                  ; ??__Ep@@YAXXZ, COMDAT
        sub     rsp, 40                             ; 00000028H
        mov     ecx, 4
        call    void * __ptr64 operator new(unsigned __int64)                      ; operator new
        mov     QWORD PTR int * __ptr64 __ptr64 p, rax                ; p
        add     rsp, 40                             ; 00000028H
        ret     0
    
    

  • 답변 # 2

    MSVC가 코드 라인을 분할하고 있습니다 :

    int *age = new int;
    
    

    두 단계로 :

                                                   ;1st step
            push        4                           ;temp var = new int
            call        operator new
            add         esp,4
            mov         dword ptr [ebp-0D4h],eax
                                                    ;2nd step    
            mov         eax,dword ptr [ebp-0D4h]    ;int *age = temp var
            mov         dword ptr [age],eax
    
    

관련 자료

  • 이전 java - MPAndroidChart 오류 클래스 ValueFormatter를 찾을 수 없음
  • 다음 javascript - js에서 모달 열기