소스 코드에서 바이너리 파일로: C++ 프로그램 여행
9787 단어 cppprogrammingcompilers
There are only two kinds of languages: the ones people complain about and the ones nobody uses.
― Bjarne Stroustrup, The C++ Programming Language
나는 호모왕CRUST의 계발을 받아서 C를 위해 자신의 컴파일러를 작성하고 싶다. 나는 러스트를 계속 사용할 것이다.그리고 shoutoutShivyC, 이것이 바로 나의 생각의 근원이다.
파이프를 컴파일하기 시작합시다!
위에서 보신 것은 NerdyElectronics.com로부터의 번역 흐름입니다.
본고에서 우리는 미리 정의된 값을 가진 간단한 덧셈 문제를 사용할 것이다.
//a.cpp program
#include <iostream>
using namespace std;
int main()
{
int firstNumber = 2, secondNumber =4, sumOfTwoNumbers;
// sum of two numbers in stored in variable sumOfTwoNumbers
sumOfTwoNumbers = firstNumber + secondNumber;
// Prints sum
cout << firstNumber << " + " << secondNumber << " = " << sumOfTwoNumbers;
return 0;
}
만약 네가 도표로 돌아간다면, 너는 우리가 현재 예처리 단계에 있다는 것을 볼 수 있을 것이다.빨리 봅시다Translation Unit.번역 단원은 헤더 파일과 확장 매크로를 포함하면 컴파일러에 입력합니다.다음 명령을 사용하여 번역 단원을 저장할 수 있습니다
g++ <filename>.cpp -E
쓰레기장이 이렇게 보여요.# 1 "a.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.cpp"
# 1 "c:\\mingw\\lib\\gcc\\mingw32\\8.2.0\\include\\c++\\iostream" 1 3
# 36 "c:\\mingw\\lib\\gcc\\mingw32\\8.2.0\\include\\c++\\iostream" 3
# 37 "c:\\mingw\\lib\\gcc\\mingw32\\8.2.0\\include\\c++\\iostream" 3
# 1 "c:\\mingw\\lib\\gcc\\mingw32\\8.2.0\\include\\c++\\mingw32\\bits\\c++config.h" 1 3
# 236 "c:\\mingw\\lib\\gcc\\mingw32\\8.2.0\\include\\c++\\mingw32\\bits\\c++config.h" 3
# 236 "c:\\mingw\\lib\\gcc\\mingw32\\8.2.0\\include\\c++\\mingw32\\bits\\c++config.h" 3
namespace std
{
typedef unsigned int size_t;
typedef int ptrdiff_t;
이것은 너무 길어서 여기에 발표할 수 없습니다. (실제로 stdio 헤더 파일을 추가했기 때문에, 이것은 1k 줄 코드와 같기 때문입니다.) 그러나 궁금하면 시스템에서 실행할 수 있습니다.조립 번호
좀 돌아봐, 하드웨어에 가까울수록 빨라진다는 소문이 있어.비록 이것은 일리가 있지만, 파이썬과 같은'느린'언어는 통상적으로 속도가 느리다. 왜냐하면 그들은 해석되거나 동적 유형으로 인해 대량의 메모리를 차지하기 때문이다.Python-to-C/C++ 컴파일러가 많고, Python을 더 빨리 작성할 수 있는 항목도 많습니다.하느님을 봐서 어떤 언어로 어떤 것을 개발하지 마라. 왜냐하면 그것은 하드웨어에 더 가깝기 때문이다.
어쨌든, 지금 우리 a.cpp 파일에서 이걸 실행하고 있습니다.
gpp a.cpp -S
지금 너는 이런 게 있을 거야. .file "a.cpp"
.text
.section .rdata,"dr"
__ZStL19piecewise_construct:
.space 1
.lcomm __ZStL8__ioinit,1,1
.def ___main; .scl 2; .type 32; .endef
LC0:
.ascii " + \0"
LC1:
.ascii " = \0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB1502:
.cfi_startproc
leal 4(%esp), %ecx
.cfi_def_cfa 1, 0
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
.cfi_escape 0x10,0x5,0x2,0x75,0
movl %esp, %ebp
pushl %ecx
.cfi_escape 0xf,0x3,0x75,0x7c,0x6
subl $36, %esp
call ___main
movl $2, -12(%ebp)
movl $4, -16(%ebp)
movl -12(%ebp), %edx
movl -16(%ebp), %eax
addl %edx, %eax
movl %eax, -20(%ebp)
movl -12(%ebp), %eax
movl %eax, (%esp)
movl $__ZSt4cout, %ecx
call __ZNSolsEi
subl $4, %esp
movl $LC0, 4(%esp)
movl %eax, (%esp)
call __ZStlsISt11char_
다시 한 번 말하지만, 시간이 너무 길어, 너 자신의 시스템에서 해 봐!이것은 당신의 목표 구조를 위해 구축될 것입니다.연습으로 당신의 시스템 구조가 무엇인지 알아보세요!이제 각 아키텍처마다 다른 명령 집합이 있습니다. 프로세서는 이 명령 집합을 이해할 수 있습니다. 컴파일러는 이를 여러 프로세스로 분해합니다.추상 문법 트리
추상적 문법 트리는 매우 좋으며 목표 구조에서 추상적으로 나온 것이다.그러나 이것은 이 용어의'추상'부분의 출처가 아니다.Wikipedia에 따르면 요약은 이러한 사실을 가리킨다. "그것은 실제 문법에 나타난 모든 세부 사항을 가리키는 것이 아니라 구조나 내용과 관련된 세부 사항을 가리킨다."AST는 구문 분석 후에 생성됩니다.모든 프로그램에서 AST를 생성할 수 있습니다.우리의 코드에 대해 이것이 바로 AST의 모습이다
다음은 너 혼자 어떻게 하는 거야?
g++ -fdump-tree-all-graph a.cpp -o a
dot -Tpng a.cpp.013t.cfg.dot -o a.png
이것은 GraphViz를 사용하여 구축된 것이므로 명령줄에 설치하십시오.또한 모든 온라인 GraphViz 시각화 도구에서 붙여넣기a.cpp.013t.cfg.dot
의 내용을 복사할 수 있습니다.객체 파일 및 링크
목표 파일에는 목표 코드가 있는데 본질적으로 기계 코드(또는 일부 중간 코드)이다.이것은 당신이 본 고전 저작 article 에서 보듯이 번역 과정의 대상입니다.내가 그 기이한'번역 과정 단계'도표를 사용하지 않은 것은 번역의 실제 과정을 약간 추상했기 때문이다.적당한 때에 우리도 이 문제를 토론할 것이다.계속하기 전에 를 사용하여 객체(.o) 파일을 작성합니다.
g++ a.cpp -c
이제 링크를 살펴보겠습니다. 대상 파일을 만든 후에 링크를 진행합니다.다른 실행 가능한 객체 파일을 만들기 위해 객체 파일이 함께 링크됩니다.이를 위해 프로그램을 헤더 파일과 주 CPP 파일로 나눕니다.//a.h
#include <stdio.h>
void printLinker()
{
printf("Hello World");
}
이제 다른 파일에서 호출합시다#include "a.h"
int main()
{
printLinker();
return 0;
}
마지막으로 링크를 표시하기 위해 다른 원본 파일을 만듭니다.//We will name this a2.cpp
void printLinker();
a.cpp를 컴파일하면 예상대로 하나 Hello World
를 줄 것입니다.그런데 링크를 봐야 돼요. 그렇죠?g++ a.h -c
g++ a.cpp -c
g++ a2.cpp -c
이제 우리는 하나가 있다.obj와 a.gch (예정된 헤더, 만약 찾을 수 없다면, 컴파일러는 헤더를 찾을 것입니다.링크하라고!gcc a.o a2.o -o a2.exe
좋아, 우리가 이 두 대상 파일을 어떻게 호출하고 컴파일하는지 봤어?지금 우리는 a2를 실행하기만 하면 된다.exe, 인쇄됩니다 Hello World
../a2.exe
Hello World
완벽했어이 파일의 내용을 보려면 nm 도구를 사용할 수 있습니다.nm a.o
당신은 다음과 같은 정보를 얻을 수 있습니다00000000 b .bss
00000000 d .data
00000000 r .eh_frame
U ___main
00000015 T _main
U _printf
00000000 r .rdata
00000000 r .rdata$zzz
00000000 t .text
00000000 T __Z7print_av
다른 대상 파일에 대해 같은 작업을 수행할 수 있습니다!파일에 포함된 내용은 매우 명확해서 잘 분할되었다.아이고, 너무 많아. 컴파일러가 이렇게 컴파일했어.나로 하여금 빨리 결론을 얻게 하다.
Reference
이 문제에 관하여(소스 코드에서 바이너리 파일로: C++ 프로그램 여행), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/abhinavmir/from-source-to-binaries-the-journey-of-a-c-program-4hlj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)