cs app(1234세션)
들어가기에 앞서
위 내용은 Randal E. Brayant의 컴퓨터 시스템 제 3판(김형신 역)을 공부하며 정리할 예정인 내용입니다.
또한 노션 블로그 바로가기를 통해 챕터별 세션별로 정리된 바로가기 및 주요내용 확인이 가능합니다.
세션1 정보의 구성요소
우리가 작성한 소스 파일들은 사실 0과 1로
구성된 비트들의 연속에 불과하다.
참고로 1바이트는 이러한 0과 1이 8개 들어간 단위인데, 각각의 바이트들은 프로그램의 텍스트 문자를 나타내준다.
아스키 코드란 무엇일까?
아스키코드는 간단하게 말하자면, 각 문자를 바이트 길이의 정수로 표현하여 컴퓨터가 처리할 수 있도록(0과 1로 이루어진 신호로 변환)해주는 변환체계이다.
아스키 코드의 정의와 내용만 살펴보아도 우리는 컴퓨터는 모든 정보를 비트로 바꾸어 소통한다는 것, 그리고 아스키 코드만으로 이루어진 파일과 다른 모든 파일의 이름이 다른 것으로 미루어보아 바이너리 파일의 경우 텍스트 파일과 변환 처리 절차가 다름을 짐작할 수 있다.
컨텍스트란
시스템 내부의 모든 정보는 0과 1로만 이루어져있다는 말을 듣고 사람에 따라서는 한가지 의문이 들었을 수 있다.
바로 시스템이 32비트라고 가정하면 컴퓨터가 처리할 수 있는 내용물의 경우의 수 즉 주소값의 경우의 수는 2의 32승 -1
개다.
그렇다면 이렇게 천문학적인 경우의 수를 모조리 코드와 대응하는 방식으로 코드가 작동하는 것일까?
그렇게 될 경우 프로그램은 어마어마하게 무거워질 것이다.
따라서 컴퓨터는 컨텍스트라는 방식을 통해 메모리에 대한 정보 및 프로세스의 번호 등을 저장해두고 컨텍스트를 통해 서로다른 객체를 사용하는 효율적 방식으로 작동한다.
즉 a라는 컨텍스트에서 사용된 주소값은 a라는 컨텍스트 범위 내에서만 유용하므로 b라는 컨텍스트 내에서는 동일한 주소값이 쓰일 수도 있다는 것이다.
세션 2 프로그램의 번역
우리가 작성한 코드는 사실, 인간들의 규약으로 이루어져있기 때문에 프로그래밍 언어를 공부한 사람이라면 누구나 편하게 이해할 수 있다.
그러나 컴퓨터의 세계는 0과 1로만 이루어져있기 때문에 모든 코드들은 0과 1로 이루어진 저급한 기계어 인스트럭션으로 번역하는 절차가 있어야만 한다.
이러한 인스트럭션들은 실행가능 목적 프로그램의 형태로 합쳐져서 바이너리 디스크 파일로 저장된다.
이러한 시스템을 작게 쪼개면 총 4단계(컴파일,전처리기,어셈블러,링커)로 나누어지며 이것들을 합쳐서 컴파일 시스템이라고 부른다.
컴파일 시스템과 단계
- 전처리기 단계: 우리가 c언어에서
#<>
로 시작하는 헤더파일을 작성하면 전처리기는 헤더파일 내에 있는 함수의 선언부들을 읽어올 수 있게 된다. - 컴파일 단계: 컴파일러가 텍스트 파일을 번역 후 어셈블리어 프로그램에 저장시킨다.
여기에는 저수준 기계어 명렁어라고 하는 텍스트가 쓰인다. - 어셈블리 단계
어셈블러가 0과 1로 이루어진 기계어 인스트럭션으로 번역한다.
이후 목적 프로그램의 형태로 묶어 목적파일에 그 결과를 저장한다. - 링크 단계: 이름과 같이 결합의 단계다.
예를 들어 printf함수를 실행하면 컴파일된 목적파일인printf.o
가 실행되어 기계어 인스트럭션으로 이루어지hello.o
와 통합작업을 수행할 수 있또록 해준다.
이후 실행가능 목적파일이 되어 메모리에 적재되고 시스템에서 실행이 된다.세션 3 컴파일 시스템 동작의 이해
컴파일러가 알아서 해주는 위의 과정들을 왜 이해하고 알아야만 하는가 의문을 표하는 사람들도 분명 있을 것이다.
거기에는 몇몇가지 이유가 있는데 최적화에 도움을 줄 뿐 아니라, 보안상의 약점들도 이러한 기계의 처리과정을 이해하지 못해 발생하는 경우가 더러 있기 때문이다.성능 최적화
최신의 컴파일러와 달리 c 프로그램 작성 시에는 올바른 판단을 위해 기계어 수준 코드에 대한 이해를 요구하는 경우가 더러 있다.
swtich구문과if-else
구문 중 어느 것이 효율적인지 골라야하는 순간이라거나, 포인터 참조가 왜 배열 인덱스를 통한 직접적 참조보다 빠른가와 같은 의문들은 기계어 수준의 코드 및 시스템 자체에 대한 이해가 있어야만 대답할 수 있는 질문들이다.
{: .notice--default}링크 에러 이해하기
정적 변수와 전역 변수의 차이는 무엇이며 링커가 어떤 참조를 풀어낼 수 없다는 오류가 뜬다면 과연 그 오류는 무엇을 의미하는 것일까?
만약 같은 파일 내에 동일한 전역변수를 정의한다면(뭐 물론 오류가 뜨겠지만)왜 안되며 어떤 문제가 생길 수 있을까?
이렇듯 c언어의 오류 메시지들은 지독히 불친절한 경우가 더러 있어 기본적인 코드가 돌아가는 방식을 이해해야만 풀 수 있는 상황도 존재한다.
보안 약점
보안에 관심이 있는 사람이라면 한번 즈음 버퍼 오버플로우
라는 말을 들어보았을 것이다.
이는 인터넷과 네트워크 상의 보안 약점의 주요 원인으로 설명되어있는데, 프로그램 스택에 데이터와 제어 정보가 저장되는 방식과 그로 인해 생겨나는 문제들을 이해하지 못해 생기는 게 다반사이다.
세션 4 프로세스: 인스트럭션 읽고 해석하기
우리가 만든 실행가능 목적파일이 유닉스에 의해 실행되기 위해서는 실행 하는 하드웨어와의 연결 및 협업과정을 거쳐야만 한다.
이에 대한 아주 기본 수준의 설명은 시스템 하드웨어 구성여기 게시물에서도 한번 공부한 내용이므로, 아래에 후술할 내용은 이 게시물에는 잘 나와있지 않은 부분 위주이다.
버스
버스 인터페이스에 대해 공부하며 인터페이스는 다리와 같은 연결지점, 그리고 버스는 그 연결지점을 통해 나를 무언가라는 정도의 내용을 가지고 있었다.
이 내용을 보다 전문적으로 설명하자면, 버스는 시스탬 내를 관통하는 전기적 배선군이며 각 컴포넌트들 간에 바이트들을 전송하는 임무를 맡고 있다.
버스는 워드라는 정보를 이루는 최소 단위(한글로 따지면 형태소처럼)로 데이터를 전송하도록 설계한다.
입출력장치
입출력장치는 외부 세계와 시스템을 연결해준다.
디스크 드라이브도 입출력장치로 분류되는데, 이는 데이터를 저장하고 다시 출력하는 과정 역시 외부 세계와 시스템을 연결하는 과정으로 보기 때문이다.
입출력 장치는 입출력 버스와 컨트롤러/어댑더
로 이루어져있다.
어댑터와 컨트롤러의 차이
- 컨트롤러: 디바이스 자체가 칩셋이거나 시스템의 인쇄기판에 장착되는 방식
- 어댑더: 머더보드의 슬롯에 장착되는 카드
메인 메모리
우리가 흔히 DRAM이라고 부르는 장치이다.
물리적으로는 DRAM칩셋들로 구성이 되어있고, 논리적으로는 포인터에서도 배웠듯 고유의 주소에 의해 돌아가는 임시 저장장치이다.프로세서
CPU는 인스터력선들을 해독하는 엔진이다.
프로세서의 중심에는 프로그램 카운터인 pc가 있는데, pc는 아주 간단하게 설명하면 기계어 인스트럭션을 가리키는 역할을 하고 프로세서는 이 pc가 가리키는 곳의 인스트럭션을 실행하는 일을 한다.프로세서의 업무처리 방식
load명령어 만들기
위 게시물에서 직접 명령어를 만들면서 공부했던 내용과 90%이상 겹치므로 따로 내용을 작성하지 않고 첨부링크로 마무리를 합니다.