CSAPP Chapter 8.1 - 예외적 제어 흐름 (Exceptional Control Flow)
서론: 제어 흐름의 기본 개념
프로그램 카운터와 제어 흐름
프로세서에 전원이 공급되는 순간부터 전원이 차단될 때까지, 프로그램 카운터(PC)는 다음과 같은 주소 시퀀스를 가정합니다:
a₀, a₁, ..., aₙ₋₁
여기서:
- 각 aₖ: 해당하는 명령어 Iₖ의 주소
- 제어 전이(Control Transfer): aₖ에서 aₖ₊₁로의 각 전환
- 제어 흐름(Control Flow): 이러한 제어 전이들의 시퀀스
일반적인 제어 흐름 패턴
1. 순차적(Smooth) 제어 흐름
- 특징: 각 Iₖ와 Iₖ₊₁이 메모리에서 인접
- 가장 단순한 형태: 연속적인 명령어 실행
2. 급작스러운 제어 흐름 변화
- 발생 조건: Iₖ₊₁이 Iₖ에 인접하지 않음
- 일반적인 원인:
- 점프(Jump) 명령어
- 호출(Call) 명령어
- 반환(Return) 명령어
- 목적: 프로그램 변수로 표현되는 내부 프로그램 상태 변화에 반응
시스템 상태 변화와 ECF의 필요성
내부 프로그램 변수로 캡처되지 않는 시스템 상태 변화들
- 하드웨어 타이머: 정기적으로 발생하는 타이머 인터럽트
- 네트워크 패킷: 네트워크 어댑터에 도착하여 메모리에 저장되어야 하는 패킷들
- 디스크 I/O: 프로그램이 디스크에서 데이터를 요청하고 데이터가 준비될 때까지 대기
- 프로세스 관리: 자식 프로세스를 생성한 부모 프로세스가 자식 프로세스 종료 알림을 받아야 함
예외적 제어 흐름 (Exceptional Control Flow, ECF)
정의: 이러한 상황들에 대응하기 위한 급작스러운 제어 흐름 변화
발생 레벨:
- 하드웨어 레벨: 하드웨어가 감지한 이벤트가 예외 핸들러로의 급작스러운 제어 전이를 트리거
- 운영체제 레벨: 커널이 컨텍스트 스위치를 통해 한 사용자 프로세스에서 다른 프로세스로 제어를 전이
- 애플리케이션 레벨: 프로세스가 다른 프로세스에 시그널을 보내어 수신자의 시그널 핸들러로 급작스러운 제어 전이
- 프로그램 레벨: 개별 프로그램이 오류에 반응하여 일반적인 스택 규칙을 우회하고 다른 함수의 임의 위치로 비지역 점프
ECF 이해의 중요성
1. 중요한 시스템 개념 이해
- ECF는 운영체제가 I/O, 프로세스, 가상 메모리를 구현하는 기본 메커니즘
- 이러한 중요한 아이디어들을 진정으로 이해하려면 먼저 ECF를 이해해야 함
2. 애플리케이션과 운영체제의 상호작용 이해
- 시스템 콜(System Call): 애플리케이션이 ECF의 한 형태인 트랩을 사용하여 운영체제 서비스를 요청
- 주요 서비스들:
- 디스크에 데이터 쓰기
- 네트워크에서 데이터 읽기
- 새 프로세스 생성
- 현재 프로세스 종료
- 기본적인 시스템 콜 메커니즘 이해가 이러한 서비스들이 애플리케이션에 제공되는 방식을 이해하는 데 도움
3. 흥미로운 새로운 애플리케이션 프로그램 작성
- 운영체제가 제공하는 강력한 ECF 메커니즘들:
- 새 프로세스 생성
- 프로세스 종료 대기
- 시스템의 예외적 이벤트를 다른 프로세스에 알림
- 이러한 이벤트 감지 및 응답
- 활용 예시: Unix 셸, 웹 서버 등
4. 동시성(Concurrency) 이해
- ECF는 컴퓨터 시스템에서 동시성을 구현하는 기본 메커니즘
- 동시성의 예시들:
- 애플리케이션 프로그램 실행을 중단하는 예외 핸들러
- 실행 시간이 겹치는 프로세스와 스레드
- 애플리케이션 프로그램 실행을 중단하는 시그널 핸들러
- ECF 이해는 동시성 이해의 첫 번째 단계 (Chapter 12에서 더 자세히 다룸)
5. 소프트웨어 예외 작동 방식 이해
- 고급 언어 예외 메커니즘: C++, Java의 try, catch, throw 문
- 소프트웨어 예외: 오류 조건에 응답하여 비지역 점프(일반적인 호출/반환 스택 규칙을 위반하는 점프) 허용
- C 언어의 비지역 점프: setjmp, longjmp 함수를 통한 애플리케이션 레벨 ECF
- 이러한 저수준 함수들의 이해가 고수준 소프트웨어 예외 구현 방식을 이해하는 데 도움
Chapter 8의 학습 목표
시스템 상호작용의 전환점
- 이전까지: 애플리케이션이 하드웨어와 상호작용하는 방식 학습
- 이번 장: 애플리케이션이 운영체제와 상호작용하는 방식 학습 시작
- 핵심: 이러한 모든 상호작용이 ECF를 중심으로 이루어짐
학습 내용 구조
1. 예외 (Exceptions)
- 위치: 하드웨어와 운영체제의 교차점
- 구현: 하드웨어와 운영체체가 부분적으로 구현
2. 시스템 콜 (System Calls)
- 정의: 애플리케이션에 운영체제로의 진입점을 제공하는 예외
3. 프로세스와 시그널 (Processes and Signals)
- 위치: 애플리케이션과 운영체제의 교차점
- 추상화 레벨: 한 단계 위의 추상화
4. 비지역 점프 (Nonlocal Jumps)
8.1 예외 (Exceptions)
예외의 정의와 특징
예외: 프로세서 상태의 어떤 변화에 응답하여 발생하는 급작스러운 제어 흐름 변화
구현 특징
- 부분적 하드웨어 구현: 하드웨어에서 부분적으로 구현
- 부분적 운영체제 구현: 운영체제에서 부분적으로 구현
- 시스템별 차이: 하드웨어에서 부분적으로 구현되므로 시스템마다 세부사항이 다름
- 공통 기본 아이디어: 모든 시스템에서 기본 아이디어는 동일
예외의 기본 구조

예외 발생 과정
- 현재 명령어 실행: 프로세서가 현재 명령어 Icurr 실행 중
- 상태 변화 감지: 프로세서 상태에 중요한 변화 발생
- 이벤트 인식: 상태 변화를 이벤트로 인식
- 예외 트리거: 이벤트에 응답하여 예외 발생
- 핸들러 호출: 예외 테이블을 통한 간접 프로시저 호출로 적절한 예외 핸들러 실행
이벤트의 종류
1. 현재 명령어 실행과 직접 관련된 이벤트
- 가상 메모리 페이지 폴트: 참조된 페이지가 메모리에 없음
- 산술 오버플로우: 계산 결과가 표현 범위를 초과
- 0으로 나누기: 나눗셈에서 0으로 나누려는 시도
2. 현재 명령어 실행과 무관한 이벤트
- 시스템 타이머: 시스템 타이머가 만료됨
- I/O 요청 완료: I/O 작업이 완료됨
예외 처리 완료 후 가능한 동작
프로세서가 이벤트 발생을 감지하면, 예외 테이블을 통해 해당 이벤트를 처리하도록 특별히 설계된 운영체제 서브루틴(예외 핸들러)을 호출합니다.
예외 핸들러가 처리를 완료하면, 예외를 발생시킨 이벤트 유형에 따라 다음 세 가지 중 하나가 발생합니다:
1. 현재 명령어로 제어 반환
- 반환 대상: Icurr (이벤트가 발생했을 때 실행 중이던 명령어)
- 사용 경우: 복구 가능한 오류 상황
2. 다음 명령어로 제어 반환
- 반환 대상: Inext (예외가 발생하지 않았다면 다음에 실행되었을 명령어)
- 사용 경우: 정상적인 예외 처리 완료
3. 중단된 프로그램 종료
- 동작: 프로그램 실행을 완전히 중단
- 사용 경우: 복구 불가능한 심각한 오류
8.1.1 예외 처리 (Exception Handling)
하드웨어와 소프트웨어의 협력
예외 처리는 하드웨어와 소프트웨어 간의 긴밀한 협력을 포함하므로 이해하기 어려울 수 있습니다. 어떤 구성요소가 어떤 작업을 수행하는지에 대해 혼동이 생기기 쉽습니다.
예외 번호 할당
예외 번호의 특징
- 고유성: 시스템의 각 가능한 예외 유형에는 고유한 음이 아닌 정수 예외 번호가 할당됨
- 할당 주체 구분:
1. 프로세서 설계자가 할당하는 번호
- 0으로 나누기
- 페이지 폴트
- 메모리 접근 위반
- 브레이크포인트
- 산술 오버플로우
2. 운영체제 커널 설계자가 할당하는 번호
커널: 메모리에 상주하는 운영체제의 부분
예외 테이블 (Exception Table)
초기화 과정
시스템 부팅 시 (컴퓨터가 리셋되거나 전원이 켜질 때):
- 운영체제가 예외 테이블이라는 점프 테이블을 할당하고 초기화
- 엔트리 k: 예외 k에 대한 핸들러의 주소를 포함
예외 테이블 구조

런타임 예외 처리 과정
1. 이벤트 감지 및 예외 번호 결정
- 시점: 시스템이 어떤 프로그램을 실행하는 런타임
- 프로세서 동작:
- 이벤트 발생 감지
- 해당하는 예외 번호 k 결정
2. 예외 핸들러 주소 계산
예외 핸들러 주소 = 예외 테이블 베이스 레지스터 + (예외 번호 × 8)
- 예외 테이블 베이스 레지스터: 예외 테이블의 시작 주소를 포함하는 특수 CPU 레지스터
- 예외 번호: 예외 테이블의 인덱스 역할
- 곱하기 8: 64비트 시스템에서 주소가 8바이트이므로
3. 간접 프로시저 호출
- 방법: 예외 테이블의 엔트리 k를 통한 간접 프로시저 호출
- 대상: 해당하는 핸들러로 제어 전이
예외와 프로시저 호출의 차이점
유사점
- 스택 사용: 핸들러로 분기하기 전에 반환 주소를 스택에 푸시
주요 차이점
1. 반환 주소의 차이
- 프로시저 호출: 항상 다음 명령어 주소
- 예외: 예외 클래스에 따라 다름
- 현재 명령어: 이벤트가 발생했을 때 실행 중이던 명령어
- 다음 명령어: 이벤트가 발생하지 않았다면 실행되었을 명령어
2. 추가 프로세서 상태 저장
- 목적: 중단된 프로그램을 핸들러 반환 시 재시작하는 데 필요
- 예시 (x86-64): 현재 조건 코드를 포함하는 EFLAGS 레지스터 등을 스택에 푸시
3. 스택 위치의 차이
- 사용자 프로그램 → 커널: 모든 항목들이 사용자 스택이 아닌 커널 스택에 푸시
- 이유: 보안과 격리를 위함
4. 실행 모드
- 예외 핸들러: 커널 모드에서 실행 (Section 8.2.4 참조)
- 권한: 모든 시스템 리소스에 완전한 접근 권한
소프트웨어에서의 예외 처리 완료
하드웨어의 역할 완료
하드웨어가 예외를 트리거하면, 나머지 작업은 예외 핸들러에 의해 소프트웨어에서 수행됩니다.
예외 핸들러의 작업 완료 후
- 이벤트 처리: 핸들러가 이벤트를 처리
- 선택적 반환: 특수한 "인터럽트로부터 반환" 명령어 실행
- 상태 복원:
- 적절한 상태를 프로세서의 제어 및 데이터 레지스터로 다시 팝
- 예외가 사용자 프로그램을 중단했다면 사용자 모드로 상태 복원 (Section 8.2.4 참조)
- 제어 반환: 중단된 프로그램으로 제어 반환
이러한 과정을 통해 예외 처리가 완료되고 시스템이 정상적인 실행을 재개할 수 있습니다.
CSAPP Chapter 8.1.2-8.1.3 - 예외 클래스와 Linux/x86-64 예외 정리
8.1.2 예외의 클래스 (Classes of Exceptions)
예외 분류 체계
예외는 네 가지 클래스로 분류됩니다: 인터럽트(Interrupts), 트랩(Traps), 폴트(Faults), 어보트(Aborts)
예외 클래스 요약표
| 클래스 | 원인 | 비동기/동기 | 반환 동작 |
|---|
| Interrupt | I/O 장치로부터의 시그널 | 비동기 | 항상 다음 명령어로 반환 |
| Trap | 의도적인 예외 | 동기 | 항상 다음 명령어로 반환 |
| Fault | 잠재적으로 복구 가능한 오류 | 동기 | 현재 명령어로 반환하거나 중단 |
| Abort | 복구 불가능한 오류 | 동기 | 절대 반환하지 않음 |
비동기 예외: 프로세서 외부의 I/O 장치 이벤트 결과로 발생
동기 예외: 명령어 실행의 직접적인 결과로 발생
1. 인터럽트 (Interrupts)
인터럽트의 특징
- 발생 방식: 프로세서 외부의 I/O 장치로부터의 시그널 결과로 비동기적으로 발생
- 비동기성: 특정 명령어의 실행으로 인해 발생하지 않음
- 핸들러 명칭: 하드웨어 인터럽트를 위한 예외 핸들러를 인터럽트 핸들러라고 부름
인터럽트 처리 과정

인터럽트 트리거 메커니즘
-
I/O 장치의 시그널링:
- 네트워크 어댑터, 디스크 컨트롤러, 타이머 칩 등이 인터럽트 트리거
- 프로세서 칩의 핀에 시그널을 보냄
- 시스템 버스에 인터럽트를 발생시킨 장치를 식별하는 예외 번호를 배치
-
프로세서의 응답:
- 현재 명령어 실행 완료
- 인터럽트 핀이 high가 된 것을 감지
- 시스템 버스에서 예외 번호를 읽음
- 적절한 인터럽트 핸들러 호출
-
핸들러 반환:
- 핸들러가 반환할 때 다음 명령어로 제어 반환
- 즉, 인터럽트가 발생하지 않았다면 제어 흐름에서 현재 명령어를 따랐을 명령어
- 효과: 프로그램이 인터럽트가 전혀 발생하지 않은 것처럼 계속 실행
2. 트랩과 시스템 콜 (Traps and System Calls)
트랩의 특징
- 발생 방식: 명령어 실행의 결과로 발생하는 의도적인 예외
- 반환 동작: 인터럽트 핸들러와 마찬가지로 트랩 핸들러는 다음 명령어로 제어 반환
- 가장 중요한 용도: 사용자 프로그램과 커널 간에 시스템 콜이라는 프로시저 유사 인터페이스 제공
시스템 콜의 필요성
사용자 프로그램이 자주 요청하는 커널 서비스들:
- read: 파일 읽기
- fork: 새 프로세스 생성
- execve: 새 프로그램 로드
- exit: 현재 프로세스 종료
시스템 콜 메커니즘
syscall 명령어
- 제공: 프로세서가 특수한
syscall n 명령어 제공
- 사용법: 사용자 프로그램이 서비스 n을 요청하고 싶을 때 실행
- 동작: syscall 명령어 실행 시 인수를 디코딩하고 적절한 커널 루틴을 호출하는 예외 핸들러로의 트랩 발생
시스템 콜 처리 과정

시스템 콜과 일반 함수 호출의 차이
프로그래머 관점
구현 관점의 차이
일반 함수:
- 실행 모드: 사용자 모드에서 실행
- 명령어 제한: 실행할 수 있는 명령어 유형에 제한
- 스택 접근: 호출 함수와 동일한 스택에 접근
시스템 콜:
- 실행 모드: 커널 모드에서 실행
- 특권 명령어: 특권 명령어 실행 허용
- 스택 접근: 커널에서 정의된 스택에 접근
- 자세한 내용: Section 8.2.4에서 사용자 모드와 커널 모드에 대해 더 자세히 논의
3. 폴트 (Faults)
폴트의 특징
- 발생 원인: 핸들러가 수정할 수 있을 가능성이 있는 오류 조건으로부터 발생
- 처리 방식: 폴트 발생 시 프로세서가 폴트 핸들러로 제어 전이
폴트 처리 결과
1. 오류 수정 성공
- 동작: 핸들러가 오류 조건을 수정할 수 있는 경우
- 반환: 폴팅 명령어로 제어 반환하여 재실행
2. 오류 수정 실패
- 동작: 핸들러가 오류를 수정할 수 없는 경우
- 반환: 폴트를 발생시킨 애플리케이션 프로그램을 종료하는 커널의 어보트 루틴으로 반환
폴트 처리 과정

페이지 폴트 예제
페이지 폴트 예외: 폴트의 고전적인 예제
발생 조건
- 명령어가 가상 주소를 참조
- 해당하는 페이지가 메모리에 상주하지 않음
- 따라서 디스크에서 검색해야 함
처리 과정
- 페이지 폴트 핸들러: 디스크에서 적절한 페이지를 로드
- 제어 반환: 폴트를 발생시킨 명령어로 제어 반환
- 명령어 재실행: 명령어가 다시 실행될 때 적절한 페이지가 메모리에 상주
- 성공적 완료: 명령어가 폴팅 없이 완료까지 실행 가능
페이지: 연속적인 가상 메모리 블록 (일반적으로 4KB)
자세한 내용: Chapter 9에서 확인
4. 어보트 (Aborts)
어보트의 특징
- 발생 원인: 복구 불가능한 치명적 오류
- 일반적 원인: DRAM이나 SRAM 비트가 손상될 때 발생하는 패리티 오류 등의 하드웨어 오류
- 반환 특성: 어보트 핸들러는 절대로 애플리케이션 프로그램으로 제어를 반환하지 않음
어보트 처리 과정

어보트 결과
- 핸들러 동작: 애플리케이션 프로그램을 종료하는 어보트 루틴으로 제어 반환
- 최종 결과: 애플리케이션 프로그램 완전 종료
8.1.3 Linux/x86-64 시스템의 예외들
예외 번호 체계
전체 예외 유형
- 총 개수: 최대 256개의 서로 다른 예외 유형
예외 번호 범위 분류
1. 범위 0-31: Intel 아키텍트 정의 예외
- 정의자: Intel 아키텍트
- 특징: 모든 x86-64 시스템에서 동일
- 예시: 프로세서 레벨에서 정의된 기본 예외들
2. 범위 32-255: 운영체제 정의 예외
- 정의자: 운영체제
- 내용: 인터럽트와 트랩
- 특징: 운영체제별로 다를 수 있음
주요 x86-64 예외 예시
| 예외 번호 | 설명 | 예외 클래스 |
|---|
| 0 | Divide error | Fault |
| 13 | General protection fault | Fault |
| 14 | Page fault | Fault |
| 18 | Machine check | Abort |
| 32–255 | OS-defined exceptions | Interrupt/Trap |
Linux/x86-64 폴트와 어보트
1. Divide Error (예외 0)
발생 조건
- 애플리케이션이 0으로 나누기를 시도
- 나눗셈 명령어의 결과가 목적지 피연산자에 비해 너무 큰 경우
처리 방식
- Unix 정책: divide error로부터 복구를 시도하지 않음
- 대신: 프로그램 중단을 선택
- 셸 보고: Linux 셸은 일반적으로 divide error를 "Floating exceptions"로 보고
2. General Protection Fault (예외 13)
발생 원인 (다양한 이유)
- 정의되지 않은 가상 메모리 영역 참조: 프로그램이 정의되지 않은 가상 메모리 영역을 참조
- 읽기 전용 텍스트 세그먼트에 쓰기 시도: 프로그램이 읽기 전용 텍스트 세그먼트에 쓰기를 시도
처리 방식
- Linux 정책: 이 폴트로부터 복구를 시도하지 않음
- 셸 보고: Linux 셸은 일반적으로 general protection fault를 "Segmentation faults"로 보고
3. Page Fault (예외 14)
특징
- 폴팅 명령어가 재시작되는 예외의 예시
- 처리 방식: 핸들러가 디스크의 적절한 가상 메모리 페이지를 물리 메모리 페이지로 매핑한 다음 폴팅 명령어를 재시작
작동 원리
- 자세한 내용: Chapter 9에서 페이지 폴트가 어떻게 작동하는지 상세히 확인
4. Machine Check (예외 18)
발생 원인
- 치명적 하드웨어 오류: 폴팅 명령어 실행 중에 감지되는 치명적 하드웨어 오류의 결과로 발생
처리 방식
- 복구 불가능: Machine check 핸들러는 절대로 애플리케이션 프로그램으로 제어를 반환하지 않음
Linux/x86-64 시스템 콜
시스템 콜 개요
제공 범위
- Linux: 애플리케이션 프로그램이 커널로부터 서비스를 요청할 때 사용할 수 있는 수백 개의 시스템 콜 제공
주요 서비스
- 파일 읽기
- 파일 쓰기
- 새 프로세스 생성
- 기타 다양한 시스템 서비스
인기 있는 Linux 시스템 콜 예시
| 번호 | 이름 | 설명 | 번호 | 이름 | 설명 |
|---|
| 0 | read | 파일 읽기 | 33 | pause | 시그널 도착까지 프로세스 일시정지 |
| 1 | write | 파일 쓰기 | 37 | alarm | 알람 시그널 전달 예약 |
| 2 | open | 파일 열기 | 39 | getpid | 프로세스 ID 얻기 |
| 3 | close | 파일 닫기 | 57 | fork | 프로세스 생성 |
| 4 | stat | 파일에 대한 정보 얻기 | 59 | execve | 프로그램 실행 |
| 9 | mmap | 메모리 페이지를 파일에 매핑 | 60 | _exit | 프로세스 종료 |
| 12 | brk | 힙의 상단 재설정 | 61 | wait4 | 프로세스 종료 대기 |
| 32 | dup2 | 파일 디스크립터 복사 | 62 | kill | 프로세스에 시그널 전송 |
시스템 콜 인터페이스
시스템 콜 점프 테이블
- 각 시스템 콜: 커널의 점프 테이블에서 오프셋에 해당하는 고유한 정수 번호를 가짐
- 주의: 이 점프 테이블은 예외 테이블과는 다름
C 프로그램에서의 시스템 콜 사용
1. 직접 호출 방법
syscall(시스템콜번호, 인수1, 인수2, ...);
2. 래퍼 함수 사용 (일반적 방법)
- C 표준 라이브러리: 대부분의 시스템 콜에 대해 편리한 래퍼 함수 집합 제공
- 래퍼 함수의 역할:
- 인수들을 패키징
- 적절한 시스템 콜 명령어로 커널에 트랩
- 시스템 콜의 반환 상태를 호출 프로그램에 다시 전달
용어 정의
- 시스템 레벨 함수: 이 텍스트에서는 시스템 콜과 관련 래퍼 함수를 상호 교환적으로 지칭
x86-64에서의 시스템 콜 구현
syscall 명령어
- 제공: x86-64 시스템에서
syscall이라는 트래핑 명령어를 통해 시스템 콜 제공
- 흥미로운 점: 프로그램이 이 명령어를 사용하여 Linux 시스템 콜을 직접 호출하는 방법 연구
인수 전달 방식
레지스터 사용 (스택 사용 안 함)
- 모든 인수: 일반 목적 레지스터를 통해 전달
- 레지스터 할당 규칙:
- %rax: 시스템콜 번호 포함
- 최대 6개 인수: %rdi, %rsi, %rdx, %r10, %r8, %r9에 순서대로 배치
- 인수 순서: 첫 번째 인수는 %rdi, 두 번째는 %rsi, 이런 식으로 계속
반환 값 처리
- 시스템 콜 반환 시:
- %rcx와 %r11: 파괴됨 (destroyed)
- %rax: 반환 값 포함
- 오류 표시: -4,095와 -1 사이의 음수 반환 값은 음수 errno에 해당하는 오류를 나타냄
시스템 콜 사용 예제
Hello 프로그램 - printf 대신 write 사용
int main()
{
write(1, "hello, world\n", 13);
_exit(0);
}
인수 설명
- 첫 번째 인수 (1): stdout으로 출력 전송
- 두 번째 인수: 쓸 바이트 시퀀스
- 세 번째 인수: 쓸 바이트 수
어셈블리 언어 버전
.section .data
string:
.ascii "hello, world\n"
string_end:
.equ len, string_end - string
.section .text
.globl main
main:
# First, call write(1, "hello, world\n", 13)
movq $1, %rax # write는 시스템 콜 1
movq $1, %rdi # Arg1: stdout은 디스크립터 1을 가짐
movq $string, %rsi # Arg2: hello world 문자열
movq $len, %rdx # Arg3: 문자열 길이
syscall # 시스템 콜 수행
# Next, call _exit(0)
movq $60, %rax # _exit는 시스템 콜 60
movq $0, %rdi # Arg1: 종료 상태는 0
syscall # 시스템 콜 수행
코드 분석
write 시스템 콜 (라인 9-13):
1. 라인 9: write 시스템 콜 번호를 %rax에 저장
2. 라인 10-12: 인수 리스트 설정
3. 라인 13: syscall 명령어로 시스템 콜 호출
_exit 시스템 콜 (라인 14-16):
1. 라인 14: _exit 시스템 콜 번호를 %rax에 저장
2. 라인 15: 종료 상태 인수 설정
3. 라인 16: syscall 명령어로 시스템 콜 호출
용어에 대한 참고사항
예외 클래스 용어의 시스템별 차이
프로세서 ISA 명세서:
- 구분: 비동기 "인터럽트"와 동기 "예외"를 구분
- 문제: 이러한 매우 유사한 개념들을 지칭하는 포괄적 용어가 없음
이 텍스트의 용어 사용:
- "예외와 인터럽트" 및 "예외 또는 인터럽트"를 계속 언급하는 것을 피하기 위해
- "예외"를 일반적인 용어로 사용
- 비동기 예외(인터럽트)와 동기 예외(트랩, 폴트, 어보트)는 적절한 경우에만 구분
중요한 점:
- 기본 아이디어: 모든 시스템에서 동일
- 제조업체 매뉴얼: 일부 제조업체는 "예외"라는 단어를 동기 이벤트로 인한 제어 흐름 변화만을 지칭하는 데 사용
따라서 독자는 시스템별로 용어 사용에 차이가 있음을 인지해야 합니다.