관리 메뉴

클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

명령어 1 - 소스 코드와 명령어 본문

알고리즘 및 자료 관리/컴퓨터 구조 & 운영체제

명령어 1 - 소스 코드와 명령어

huenuri 2024. 10. 14. 22:24

개발자가 프로그래밍 언어로 작성한 소스 코드가 컴퓨터 내부에서 명령어가 되고 실행되는 과정을 학습해 볼 것이다.

 

 

 

컴퓨터를 작동시키는 정보가 명령어라면 C, C++, Java, Python과 같은 프로그래밍 언어로 만든 소스 코드는 무엇일까? 결론부터 말하면 모든 소스 코드는 컴퓨터 내부에서 명령어로 변환된다.

 

 

 

이번 절에서는 프로그래밍언어가 어떻게 명령어가 되어 실행되는지 알아보겠다.


 

 

 

 

고급 언어와 저급 언어

우리가 프로그램을 만들 때 사용하는 프로그래밍 언어는 컴퓨터가 이해하는 언어가 아닌 사람이 이해하고 작성하기 쉽게 만들어진 언어이다. 컴퓨터는 이 언어를 이해하지 못한다. 이렇게 '사람을 위한 언어'고급 언어라고 한다.

반대로 컴퓨터가 직접 이해하고 실행할 수 있는 언어저급 언어라고 한다.

 

 

고급 언어로 작성된 소스 코드가 실행되려면 반드시 저급 언어, 즉 명령어로 변환되어야 한다.

 

 

 

 

저급 언어는 두 가지 종류가 있다.

 

 

 

 

기계어란 0과 1로 이루어진 명령어 모음이다. 위 그림처럼 기계어를 이진수로 나열하면 너무 길어지기 때문에 가독성을 위해 16진수로 표현하기도 한다.

 

 

 

기계어는 오로지 컴퓨터만을 위해 만들어진 언어이기 때문에 사람이 읽으면 그 의미를 이해하기 어렵다. 그래서 등장한 저급 언어가 어셈블리어이다.

0과 1로 표현된 명령어(기계어)를 읽기 편한 형태로 번역한 언어가 어셈블리어이다.

 

 

이것이 어셈블리어이다. 이 한줄 한 줄이 컴퓨터를 동작시키는 명령어라고 보면 된다.

어셈블리어는 0과 1로 이루어진 기계어를 읽기 편하게 만든 저급언어일 뿐이므로, 개발자가 어셈블리어를 이용해 복잡한 프로그램을 만들기란 쉽지 않다. 그래서 고급 언어가 필요하다. 고급 언어는 사람이 읽고 쓰기 편한 것은 물론이고, 더 나은 가독성, 변수나 함수 같은 편리한 문법을 제공하기 때문에 어떤 복잡한 프로그램도 구현할 수 있다.

 

"그러면 왜 저급 언어를 알아야 할까?" 자신이 어떤 개발자가 되길 희망하는지에 따라 저급 언어의 중요성이 달라진다. 어셈블리어를 작성하거나 관찰할 일이 거의 없는 개발자도 있다. 하지만 하드웨어와 밀접하게 맞닿아 있는 임베디드 개발자, 게임 개발자, 정보 보안 분야의 개발자는 아래와 같이 어셈블리어를 많이 이용한다.

 

 

 

그리고 이러한 분야의 개발자에게 어셈블리어란 '작성의 대상'일 뿐만 아니라 매우 중요한 '관찰의 대상'이기도 하다. 어셈블리어를 읽으면 컴퓨터가 프로그램을 어떤 과정으로 실행하는지, 즉 프로그램이 어떤 절차로 작동하는지를 가장 근본적인 단계에서부터 하나하나 추적하고 관찰할 수 있기 때문이다.


 

 

 

 

컴파일 언어와 인터프리터 언어

 

고급 언어는 어떻게 저급 언어로 변환될까? 여기에는 크게 컴파일과 인터프리트 방식이 있다. 컴파일 방식으로 작동하는 프로그래밍 언어를 컴파일 언어, 인터프리트 방식으로 작동하는 프로그래밍 언어를 인터프리터 언어라고 한다.

 

 

컴파일 언어

 

 

컴파일 언어컴파일러에 의해 소스 코드 전체가 저급 언어로 변환되어 실행되는 고급 언어이다. 대표적인 컴파일 언어로는 C가 있다. 컴퓨터는 개발자가 만든 소스 코드를 이해하지 못하므로 컴파일 언어로 작성된 소스코드는 코드 전체가 저급 언어로 변환되는 과정을 거친다. 이 과정을 컴파일이라고 한다. 그리고 컴파일을 수행해주는 도구컴파일러라고 한다.

컴파일러는 개발자가 작성한 소스 코드 전체를 쭉 훑어보며 소스 코드에 문법적인 오류는 없는지, 실행 가능한 코드인지, 실행하는데 불필요한 코드는 없는지 등을 따지며 소스 코드를 처음부터 끝까지 컴파일한다.

컴파일이 성공적으로 수행되면 개발자가 작성한 소스 코드는 컴퓨터가 이해할 수 있는 저급 언어로 변환된다. 이렇게 컴파일러를 통해 저급 언어로 변환된 코드를 목적 코드라고 한다. 

 

C나 C++ 개발자를 지향한다면 이것보다는 좀 더 자세히 학습하는 것이 좋다.


 

 

 

인터프리터 언어

소스 코드를 한 줄씩 저급 언어로 변환하여 실행해 주는 도구를 인터프리터라고 한다. 인터프리터 언어는 컴퓨터와 대화하듯 소스 코드를 한 줄씩 실행하기 때문에 소스 코드 전체를 저급 언어로 변환하는 시간을 기다릴 필요가 없다.

 

 

인터프리터 언어가 컴파일 언어보다 빠르다고 생각할 수 있지만, 일반적으로 인터프리터 언어는 컴파일 언어보다 느리다. 컴파일을 통해 나온 결과물, 즉 목적 코드는 컴퓨터가 이해하고 실행할 수 있는 저급 언어인 반면, 인터프리터 언어는 소스 코드 마지막에 이를 때까지 한 줄 한 줄씩 저급 언어로 해석하며 실행해야 하기 때문이다.

 

 

 

 

컴파일 언어가 독일어로 쓰인 책(소스 코드) 전체를 한국어로 번역한 뒤 번역된 책(목적 코드)을 친구에게 건네주는 방식이라면, 인터프리터 언어는 독일어로 쓰인 책을 한 주씩 한국어로 설명해 주는 방식이라고 보면 된다.


 

 

 

컴파일과 인터프리터 과정 실습해보기

 

Compiler Explorer

 

godbolt.org

 

 

왼쪽에 사용할 프로그래밍 언어를 선택하면 오른쪽에 어셈블리어로 번역되어 나온다. 하지만 우리가 사용하는 CPU, 컴파일러의 종류에 따라 변환된 저급 언어의 모습은 달라질 수 있다.

여기서 X86-64는 CPU의 종류이고, gcc 14.2는 컴파일러의 종류라고 보면 된다.

 

 

 

이 종류를 바꾸자 어셈블리어가 달라진 것을 볼 수 있다. 우리가 작성한 프로그래밍 언어는 바로 실행되는 것이 아니라 컴퓨터가 알아들을 수 있는 저급 언어로 변환된 후에 이것을 실행하는 것을 기억하자.

이제 다른 언어도 한번 선택해 볼 것이다.

 

 

 

파이썬에서는 오른쪽 번역이 많이 달라졌는데 이것은 파이썬 인터프리터에 의해 생성된 소스 코드를 변환한 결과물인 중간 과정의 코드인 바이트 코드이다. 


 

 

 

 

현대의 많은 프로그래밍 언어 중에는 둘이 서로 양분되는 것이 아니라 컴파일 언어와 인터프리터 언어 간의 경계가 모호한 경우가 많다. 가령 대표적인 인터프리터 언어로 알려진 Python도 컴파일을 하지 않는 것은 아니며, Java의 경우 저급 언어가 되는 과정에서 컴파일과 인터프리트를 동시에 수행한다.

즉, 하나의 프로그래밍 언어가 반드시 둘 중 하나의 방식만으로 작동한다고 생각하는 것은 오개념이다. 따라서 모든 프로그래밍 언어를 컴파일 언어와 인터프리터 언어로 칼로 자르듯 구분하기보다는 '고급 언어가 저급 언어로 변환되는 대표적인 방법에는 컴파일 방식과 인터프리트 방식이 있다' 정도로만 이해하는 것이 좋다.


 

 

 

 

단원 마무리하기

 

 

2번 문제에서 3번 이 조금 헷갈렸다. 저급 언어로 변환되는 것이 맞는지 의문이 들었는데 컴파일러를 통해 소스 코드인 고급언어를 목적 코드인 저급 언어로 변환되는 것이다.

 


 

 

 

학습을 마치고

많지 않은 분량이어도 꼼꼼히 학습하니 시간은 전보다 많이 걸리는 것 같다. 지난번에 머신러닝 공부할 때는 솔직히 별로 흥미가 많지 않은 과목이라 대충 공부했었다. 그러다 세 번쯤 복습을 하니 그 과목의 가닥이 잡혔다. 

이번에는 처음부터 구미가 당기는 과목이라서 그런지 더 알고 싶고 한 가지라도 놓치고 싶지 않았다. 이제 3단원 학습도 한 가지 남았는데 여기까지는 공부를 하고 오늘을 마무리하고 싶다.