티스토리 뷰
3.6 제어문
기계어 코드에서는 조건부 동작을 구현하기 위해 두 개의 기본적인 row level의 방법을 제공한다.
보통 C와 기계어 코드의 인스트럭션들은 모두 프로그램에 나타나는 순서대로 순차적으로 실행된다. 기계어 인스트럭션들의 실행 순서는 점프(jump) 인스트럭션으로 변경할 수 있다. 점프 인스트럭션은 결과에 따라 프로그램의 다른 일부분으로 제어를 넘겨준다.
3.6.1 조건 코드
정수 레지스터들과 함께 최근 CPU는 가장 최근 산술 또는 논리연산의 특성을 설명하는 단일 비트 조건 코드로 구성된 레지스터들을 운영한다.
- CF: Carry Flag. 가장 최근의 연산에서 가장 중요한 비트로부터 받아 올림이 발생한 것을 표시 비부호형 연산에서 오버플로우를 검출할 때 사용
- ZF: Zero Flag. 가장 최근 연산의 결과가 0인 것을 표시
- SF: Sign Flag. 가장 최근 연산이 음수를 생성한 것을 표시
- OF: Overflow Flag. 가장 최근 연산이 양수/음수의 2의 보수 오버플로우를 발생시킨 거을 표시
위의 인스트럭션 클래스는 다른 레지스터들은 변경시키지 않으면서 조건 코드만 변경해준다.
- CMP
- 두 오퍼랜드의 차에 따라 조건 코드를 설정한다.
- 목적지를 갱신하지 않고 조건 코드를 설정한다는 점을 제외하고는 SUB 인스트럭션과 같은 방법으로 동작한다.
- TEST
- 목적지 오퍼랜드를 변경하지 않으면서 조건 코드를 설정한다는 점을 제외하고는 AND 인스트럭션과 같은 방식으로 동작한다.
- 예를 들어
%rax
가 음수인지, 0인지, 양수인지 알기 위해서는testq %rax, %rax
와 같이 사용한다.
3.6.2 조건 코드 사용하기
조건 코드를 이용하는 보편적인 세 가지 방법이 있다.
- 조건 코드의 조합에 따라 0 또는 1을 한 개의 바이트에 기록하는 방법
- 조건에 따라 프로그램의 다른 부분으로 이동하는 방법
- 조건에 따라 데이터를 전송하는 방법
3.6.3 점프(Jump) 인스트럭션
일반적으로 인스트럭션들은 나열된 순서에 따라 순차적으로 실행된다. 점프 인스트럭션은 프로그램이 완전히 새로운 위치로 실행을 전환하도록 한다. 점프의 목적지는 어셈블리 코드에서는 레이블(label) 로 표시한다. 예를 들면 다음과 같다.
movq $0, %rax // Set %rax to 0
jmp .L1 // Goto .L1
movq (%rax), %rdx // Null pointer dereference (skipped)
.L1:
popq %rdx // Jump target
인스트럭션 jmp .L1
은 프로그램이 movq
인스트럭션을 건너뛰는 대신에 popq
로 실행을 다시 시작하게 한다. 목적 코드 팡리을 만들기 위해서 어셈블러는 모든 레이블에 붙은 인스트럭션들의 주소를 결정하고, 점프 인스트럭션의 일부분인 점프 목적지(목적지 인스트럭션의 주소)를 인코딩한다.
점프 방식은 두가지가 있다.
- 직접 점프
- 점프 목적지가 인스트럭션의 일부로 인코딩되는 경우
- e.x) 상단의
.L1
과 같은 경우
- 간접 점프
- 점프 대상을 레지스터나 메모리 위치로부터 읽어들여야 하는 경우
- e.x)
jmp *%rax*
:%rax
에 저장된 값을 읽기 주소로 사용하여 메모리에서 점프 목적지를 읽어들인다.
3.6.4 점프 인스트럭션 인코딩
어셈블리 코드에서 점프 목적지는 심벌 레이블을 사용해서 작성한다. 어셈블러와 링커는 점프 목적지를 적절히 인코딩한다. 점프 인스트럭션을 인코딩 하는 방법에는 두가지가 있다.
- 가장 일반적인 점프 인코딩 방법은
PC relative(PC 상대적)
방법이다. 즉, 대상 인스트럭션과 점프 인스트럭션 바로 다음에 오는 인스트럭션 주소와의 차이를 인코딩한다. - 두 번째 인코딩 방법은
절대 주소를 제공
하는 방법이다. 이 방법은 대상을 직접 명시하기 위해 4바이트를 사용한다.
3.6.7 반복문
C에서는 do-while
, while
, for
과 같은 여러가지 반복문 구문을 제공한다. 기계어에는 여기에 대응되는 인스트럭션은 없다. 그 대신에 조건부 테스트와 점프를 함께 사용해서 반복문의 효과를 구현한다.
Do-While문
- do-while문장의 일반적인 형태는 다음과 같다.
do body-statement while (test-expr);
- body-statement를 반복적으로 실행하고, test-expr를 계산하여 그 결과가 0이 아니면 반복 수행을 계속 한다. body-statement가 적어도 한 번은 실행된다는 점에 주목해야한다. 이러한 일반 형식을 조건문과 goto문으로 변환하면 다음과 같다.
loop:
body-statement
t = test-expr;
if (t)
goto loop;
- 즉, 매 실행마다 프로그램은 본체 문장과 테스트 수식을 계산한다.
While 루프
while (test-expr)
body-statement
- while문은 test-expr를 먼저 계산해서, body-statement를 실행하기 전에 종료될 수 있다는 점에서 do-while문과 다르다. 이 둘은 do-while 루프에서 우리가 본 것과 루프 구조가 동일하고, 초기 테스트의 구현방법에서만 다르다. 이러한 구현 전략을 이용해서 컴파일러는 종종 테스트 조건이 항상 만족되는지 결정하는 것 같은 초기 테스틀르 최적화 할 수 있다.
For 루프문
for 반복문의 일반적인 유형은 다음과 같다.
for (init-expr; test-expr; update-expr)
body-statement
- 프로그램은 먼저 초기화 수식인 init-expr를 계산한다. 테스트 조건인 test-expr를 계산하는 곳에서 루프에 들어가며, 테스트가 실패하면 루프를 빠져나오고, 반복문 body-statement를 실행하며, 마지막으로 update-expr를 계산한다.
3.6.8 Switch문
Switch문은 정수 인덱스 값에 따라 다중분기 기능을 제공한다. 이것은 테스트해야 하는 경우의 수가 많은 경우에 특히 유용하다. Switch문을 사용하면 C 코드를 읽기 쉽게 해 줄 뿐만 아니라 점프 테이블(원소 i가 switch문의 인덱스가 i일 때 프로그램이 실행해야 하는 동작을 구현하는 코드 블록의 주소가 되는 배열)이라는 자료구조를 사용해서 효율적인 구현을 가능하게 한다.
이 코드는 점프 인스트럭션의 목적지를 찾아내기 위해서 switch문의 인덱스를 사용하여 점프 테이블을 배열처럼 참조한다. 점프 테이블을 사용하면 if-else문을 사용하는 것보다 switch문을 실행하는데 걸리는 시간이 case의 수에 관계없다는 점이 장점이다.
'Computer science > CSAPP' 카테고리의 다른 글
Chapter 3. 프로그램의 기계수준 표현 - 4 (0) | 2022.10.04 |
---|---|
Chapter 3. 프로그램의 기계수준 표현 - 3 (0) | 2022.09.27 |
Chapter 3. 프로그램의 기계수준 표현 - 1 (0) | 2022.09.25 |
Chapter 2. 정보의 표현과 처리 - 2 (0) | 2022.09.22 |
Chapter 2. 정보의 표현과 처리 - 1 (0) | 2022.09.21 |
- Total
- Today
- Yesterday
- kafka
- 빅데이터를지탱하는기술
- DP
- DFS
- 빅데이터
- CSAPP
- 이코테
- OS
- oozie
- CS
- mahout
- BOJ
- 파이썬
- cka
- logstash
- sqoop
- 백준
- HDFS
- Espher
- Flutter
- kubernetes
- Algorithm
- heapq
- elasticsaerch
- GROK
- 프로그래머스
- 네트워크
- Elasticsearch
- Hadoop
- Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |