[visual-c++] Visual C ++를 사용하여 코드 뒤의 어셈블리를 보는 방법은 무엇입니까?

나는 두 줄의 코드의 효율성에 관한 또 다른 질문을 읽고 있었고 OP는 그가 코드 뒤의 어셈블리를 보았고 두 줄이 어셈블리에서 동일하다고 말했습니다. 여담을 제외하고, 프로그램이 컴파일 될 때 생성 된 어셈블리 코드를 어떻게 볼 수 있습니까?

Microsoft의 Visual C ++를 사용하고 있지만 Visual Basic으로 작성된 코드 뒤에있는 어셈블리를 볼 수 있는지도 알고 싶습니다.

그렇다면 C ++ 및 Visual Basic과 같은 고급 언어로 작성된 프로그램 뒤에있는 어셈블리 코드를 어떻게 볼 수 있습니까?



답변

몇 가지 접근 방식이 있습니다.

  1. Visual Studio (및 Eclipse도)에서 C ++를 디버깅하는 동안 일반적으로 어셈블리 코드를 볼 수 있습니다. 이를 위해 Visual Studio에서 문제의 코드에 중단 점을 설정하고 디버거가이를 때리면 클릭하고 “어셈블리로 이동”을 찾습니다 (또는 CTRL + ALT + D를 누릅니다).

  2. 두 번째 방법은 컴파일하는 동안 어셈블리 목록을 생성하는 것입니다. 이를 위해 프로젝트 설정-> C / C ++-> 출력 파일-> ASM 목록 위치로 이동하여 파일 이름을 입력합니다. 또한 “Assembly Output”을 “Assembly With Source Code”로 선택합니다.

  3. 프로그램을 컴파일하고 타사 디버거를 사용하십시오. 이를 위해 OllyDbg 또는 WinDbg를 사용할 수 있습니다. 또한 IDA (대화 형 디스어셈블러)를 사용할 수 있습니다. 그러나 이것은 그것을하는 하드 코어 방법입니다.


답변

추가 참고 사항 : 디버그 어셈블러 출력과 릴리스 1 사이에는 큰 차이가 있습니다. 첫 번째는 컴파일러가 C ++에서 어셈블러 코드를 생성하는 방법을 배우는 데 좋습니다. 두 번째는 컴파일러가 다양한 C ++ 구문을 최적화하는 방법을 배우는 데 좋습니다. 이 경우 일부 C ++에서 asm으로의 변환이 명확하지 않습니다.


답변

cl 컴파일러에 대해 / FA 스위치를 지정합니다. 스위치의 값에 따라 어셈블리 코드 또는 고급 코드 및 어셈블리 코드 만 통합됩니다. 파일 이름은 .asm 파일 확장자를 갖습니다. 지원되는 값은 다음과 같습니다.


  • / FA 어셈블리 코드; .asm
  • / FAc 기계 및 조립 코드; .대구
  • / FAs 소스 및 어셈블리 코드; .asm
  • / FAcs 기계, 소스 및 어셈블리 코드; .대구

답변

가장 쉬운 방법은 디버거를 실행하고 디스 어셈블리 창을 확인하는 것 입니다.


답변

이 답변의 이전 버전 (rextester.com의 “해킹”)은 http://gcc.godbolt.org/ 에서 ARM, x86 및 x86-64 용 CL 19 RC 를 제공 하므로 대부분 중복됩니다 (Windows 호출 규칙을 대상으로 함). , 해당 사이트의 gcc, clang 및 icc와 달리).

Godbolt 컴파일러 탐색기는 컴파일러 asm 출력을 멋지게 형식화하고 지시문의 “노이즈”를 제거하도록 설계되었으므로 인수를 취하고 값을 반환하는 간단한 함수에 대해 asm을 살펴볼 때 사용하는 것이 좋습니다 (그러므로 최적화).

잠시 동안 CL은 http://gcc.beta.godbolt.org/ 에서 사용할 수 있었지만 메인 사이트는 아니었지만 지금은 둘 다에 있습니다.


http://rextester.com/l/cpp_online_compiler_visual 온라인 컴파일러 에서 MSVC asm 출력을 얻으려면 : /FAs명령 줄 옵션에 추가 합니다. 프로그램이 자체 경로를 찾고 경로를 찾아서 .asm덤프하도록하십시오. 또는 .exe.

예 : http://rextester.com/OKI40941

#include <string>
#include <boost/filesystem.hpp>
#include <Windows.h>

using namespace std;

static string my_exe(void){
    char buf[MAX_PATH];
    DWORD tmp = GetModuleFileNameA( NULL, // self
                                  buf, MAX_PATH);
    return buf;
}

int main() {
    string dircmd = "dir ";
    boost::filesystem::path p( my_exe() );
    //boost::filesystem::path dir = p.parent_path();

    // transform c:\foo\bar\1234\a.exe 
    // into      c:\foo\bar\1234\1234.asm
    p.remove_filename();
    system ( (dircmd + p.string()).c_str() );

    auto subdir = p.end();      // pointing at one-past the end
    subdir--;                   // pointing at the last directory name
    p /= *subdir;               // append the last dir name as a filename
    p.replace_extension(".asm");
    system ( (string("type ") + p.string()).c_str() );
//    std::cout << "Hello, world!\n";
}

... code of functions you want to see the asm for goes here ...

type의 DOS 버전입니다 cat. asm을보고 싶은 함수를 찾기 어렵게 만드는 더 많은 코드를 포함하고 싶지 않았습니다. (그 목표에 표준 : : 문자열과 부스트 런 카운터를 사용하지만!이 처리 (그리고있어 문자열에 대한 자세한 가정을 일부 C 스타일의 문자열 조작의 결과에) 큰 버퍼를 사용하여 최대 길이 안전 / 할당을 무시 GetModuleFileNameA겠습니까 전체 기계 코드가 훨씬 적습니다.)

IDK cout << p.string() << endl는 그 길이를 인쇄하는 것이 단순한 이름이 아니라는 것을 보여도 기본 이름 (즉, 디렉토리없이 파일 이름) 만 표시합니다. (Ubuntu 15.10의 Chromium48). 에서 cout또는 프로그램의 표준 출력과 웹 브라우저 사이 에 백 슬래시 이스케이프 처리가있을 수 있습니다 .


답변

Visual C ++에서 출력 파일 아래의 프로젝트 옵션에는 소스 코드와 함께 ASM 목록을 출력하는 옵션이 있습니다. 따라서 C / C ++ 소스 코드와 결과 ASM이 모두 동일한 파일에 표시됩니다.


답변

MSVC의 경우 링커를 사용할 수 있습니다.

link.exe / dump / linenumbers / disasm /out:foo.dis foo.dll

기호를 얻으려면 foo.pdb를 사용할 수 있어야합니다.