
많은 디버거 등을 사용하여 C++ 코드에서 동등한 어셈블리를 덤프할 수 있다는 것을 알고 있습니다.
하지만 바이너리 코드는 어떻습니까? 마이크로프로그램(마이크로아키텍처에 있는 경우)을 구성할 수 있는 실제 기계 명령을 구성하는 각 바이트의 비트 형식입니다.
C++ 코드의 각 행이 어떤 방식으로든 프로그램의 특정 지점에서 기계어 코드로 변환되어야 하는 경우(예: C++에서 부동 소수점을 정의할 수 있지만 스택에 푸시될 때까지는 아무 쓸모가 없으므로 변환되지 않을 수 있습니다. 1: 1은 모든 기계어 코드를 한 줄씩 사용하지만 관계없이 사용됩니다), 각 명령문 등을 추적할 수 있습니다. 그러나 디버거는 각 개별 명령어를 차지하는 비트 형식을 출력하지 않습니다.
각 프로그램이 CPU에 대한 형식화된 바이트/비트 패턴 명령이 되면 회로 수준에서 실제 비트에 작성한 모든 코드를 추적하는 것이 가능해야 합니다.
그러나 최대한의 보장을 위해,가능합니까?내가 여기서 설명하는 정도까지 이 작업을 수행하려면? 최신 디버거/소프트웨어는 이 기능을 제공하지 않으며, 개발자에게 각 명령의 전체 바이너리 표현을 명확하게 제공하지 않는 것 같은 디버거/소프트웨어도 제공하지 않습니다.
추신: 물론 이는 컴파일된 코드가 의도한 아키텍처에 대한 지침으로 쉽게 실행 가능하다고 가정합니다(일부 해석된 언어나 추가 번역을 위해 다른 프로그램이 필요한 바이트코드는 아님).
답변1
디스어셈블러를 사용하여 컴파일된 바이너리 코드를 다시 어셈블리 언어로 변환할 수 있습니다. 그러면 바이너리로만 배포된 소프트웨어를 "읽기"(어려움)할 수 있습니다.
질문의 다른 부분에서는 CPU가 특정 바이너리 명령을 실행하는 방법에 대한 자세한 정보를 제공하는 일종의 하드웨어 디컴파일러를 원하는 것 같습니다. 나는 이것을 수행하는 도구를 모른다. 아마도 하드웨어 매뉴얼을 읽고 이런 종류의 분석을 머릿속으로 수행해야 할 것입니다.
답변2
아니요.
글쎄요, 그럴 수도 있겠지만 컴파일러에 들어가는 코드가 나오는 코드와 거의 동일하지 않기 때문에 보장할 수는 없습니다. 두 가지 이유가 있습니다. 인간은 효율적인 코드를 작성하는 데 서툴고 인간은 코드에 대해 같은 방식으로 생각하지 않습니다. CPU가 이를 처리해야 합니다. 이로 인해 컴파일러는 소스 코드를 어셈블리/바이너리로 변환하기 전에 최적화합니다. 이는 다음으로 이어질 수 있습니다.문이 재정렬되고, 쓸모없는 문이 제거되고, 전체 함수가 인라인됩니다..
예를 들어 다음과 같은 의사코드가 있다고 가정해 보겠습니다.
int x = 3;
x = 3*3;
x = 4;
function mult4(number) { return number * 4; }
x = mult4(x);
완전히 줄일 수 있습니다
int x = 16;
소스와 전혀 일치하지 않는 좋은 최적화 컴파일러에 의해. 이것이 디버깅할 때 컴파일러 최적화를 비활성화해야 하는 이유입니다. 모든 컴파일러 최적화가 비활성화되면 컴파일러는 소스 코드와 1:1로 일치하는 어셈블리를 출력하려고 시도합니다.