교재처럼 순서대로 읽는 본문
이 글은 요약 카드가 아닙니다. 처음 보는 용어의 뜻부터 시작해, 왜 그런 규칙이 생겼는지와 문제에서 어떻게 사용하는지를 한 흐름으로 설명합니다.
이 장을 공부하는 이유
C 문장을 한 줄씩 기계적으로 바꾸는 것이 아닙니다. 변수의 보관 장소를 먼저 정하고, array 주소, loop 탈출 조건, function call 보존 규칙을 작은 패턴으로 조립합니다.
읽고 나면 할 수 있어야 하는 것
- arr[i] 주소를 base + i×element_size로 만든다.
- loop의 계속 조건을 반대인 탈출 branch로 바꾼다.
- caller/callee-saved register와 16-byte stack alignment를 지킨다.
먼저 비유로 머릿속 구조 만들기
register는 책상 위의 메모지입니다. t-register는 전화를 걸면 상대가 지워도 되는 임시 메모, s-register는 상대가 사용했다면 원상복구해야 하는 장기 메모, stack은 통화 전에 중요한 메모를 넣어 두는 서랍입니다.
그림은 왼쪽에서 오른쪽으로 읽습니다. 각 화살표는 앞 단계의 결과가 다음 단계의 입력이 된다는 뜻입니다. 흐름도만 크게 열기
용어를 평범한 문장으로 바꾸기
독일어와 영어 용어를 소리만 외우지 말고, 아래 설명을 자신의 말로 다시 말해 보세요.
- ABI / calling convention
- 함수끼리 register·stack을 어떻게 주고받는지 정한 약속
- Prolog / Epilog
- 함수 시작의 저장·frame 생성 / 끝의 복원·return
- leaf function
- 다른 함수를 호출하지 않는 함수
- byte offset
- 원소 index를 실제 주소에 더할 Byte 수로 바꾼 값
- branch inversion
- 계속 조건의 반대를 검사해 done label로 빠지는 구성
개념을 처음부터 연결하기
1. Array 주소 공식
`&arr[i] = base + i × sizeof(element)`입니다. int는 4 Byte이므로 `slli offset,i,2`로 ×4를 만들 수 있습니다. load/store offset은 Byte 단위입니다.
2. 함수 호출 전후
`jal`은 ra를 덮어씁니다. 호출 뒤에도 필요한 값은 caller-saved t/a에 그대로 믿고 두지 않습니다. s-register를 쓰는 함수는 caller의 원래 s값을 stack에 저장했다가 복원합니다.
3. Loop와 if
`i < n-1`이 참일 때 body로 가는 대신 `i >= n-1`이면 done으로 가도록 씁니다. 조건 반전과 branch target을 한 묶음으로 검산해야 합니다.
이 챕터에서 계속 사용할 손풀이 표
아래 표는 정답표가 아니라 작업 기억을 외부에 꺼내 놓는 worksheet입니다. 소문제를 풀 때마다 빈 칸을 직접 채우세요.
| C 요소 | Assembly에서 정할 것 | 검산 |
|---|---|---|
| 변수 | 보관 register | call 뒤에도 살아 있는가 |
| Array | base + index×size | Byte 단위인가 |
| Loop | init·condition·body·update | 탈출 조건이 반대인가 |
| Function call | argument·ra·saved values | ABI 보존 규칙 |
| Return | a0와 epilog | stack이 원상복구됐는가 |
수식은 위아래 구조로 읽기
평문으로 제곱과 분수를 이어 쓰면 구조를 놓치기 쉽습니다. 아래 수식은 브라우저의 MathML로 렌더되며, 지수·아래첨자·분수를 실제 수학 표기처럼 보여 줍니다.
int array 원소의 주소
RISC-V의 load/store offset은 원소 수가 아니라 Byte 수입니다.
함수 호출 경계의 stack 정렬
저장할 값이 20 Byte여도 frame은 정렬을 만족하도록 32 Byte처럼 올림할 수 있습니다.
작은 숫자로 한 번 직접 해보기
`arr[3]`의 주소를 구해 봅시다. base=0x1000, int=4 Byte이면 offset=3×4=12=0xC, 주소=0x100C입니다. index 3을 그대로 더한 0x1003은 misaligned 주소라 틀립니다.
이 예제에서 중요한 것은 숫자 자체가 아니라, 어떤 값을 먼저 구하고 그 결과를 다음 계산에 넣는지입니다. 종이에 중간값을 생략하지 않고 적어 보세요.
초보자가 자주 멈추는 지점
C 한 줄은 Assembly 한 줄인가요?
아닙니다. `arr[i]` 하나에도 index scaling, base addition, load/store가 필요합니다. 의미가 같은지가 기준이지 줄 수가 기준이 아닙니다.
t-register는 함수 안에서 자유롭게 안전한가요?
현재 함수가 helper를 호출하면 helper가 t-register를 바꿀 수 있습니다. 호출 뒤에도 필요한 값은 반드시 따로 보호해야 합니다.
loop branch 방향이 계속 헷갈려요.
C의 계속 조건을 먼저 쓰고 그 부정을 done 조건으로 옆에 씁니다. 예: `j < limit`의 부정은 `j >= limit`, 따라서 `bge j,limit,done`입니다.
시험지에서 손으로 쓰는 순서
- C variable마다 register 표를 먼저 만듭니다.
- 호출 여부를 보고 stack frame과 저장 register를 결정합니다.
- array 접근마다 base + index×size를 적습니다.
- loop마다 init / condition / body / update / back-edge 다섯 칸을 만듭니다.
- epilog에서 prolog의 역순으로 정확히 복원합니다.
이 순서를 외우는 목적은 답을 암기하는 것이 아닙니다. 중간 과정을 답안지에 남겨 부분점수를 얻고, 어디에서 잘못됐는지 스스로 찾기 위한 체크포인트입니다.
6개 소문제로 개념 적용하기
각 소문제에는 이 장의 설명을 다시 포함한 독립 수업 페이지가 있습니다. 따라서 링크로 바로 들어가도 선행지식 없이 읽을 수 있습니다.
- 3-1`swap`: 두 주소 계산독립 수업 열기 →
`arr[i]`와 `arr[j]`의 주소를 만드세요. · 4 micro-work
- 3-2`swap`: load 두 번, store 두 번독립 수업 열기 →
두 원소를 실제로 바꾸세요. · 5 micro-work
- 3-3`bubbleSort` Prolog독립 수업 열기 →
swap을 부르기 전에 무엇을 stack에 저장해야 하나요? · 4 micro-work
- 3-4바깥 loop 조건독립 수업 열기 →
`i < n-1`을 branch로 구현하세요. · 3 micro-work
- 3-5안쪽 loop와 비교독립 수업 열기 →
`j < n-i-1`과 `arr[j] > arr[j+1]`을 구현하세요. · 5 micro-work
- 3-6swap 호출과 Epilog독립 수업 열기 →
argument를 놓고 swap을 호출한 뒤 loop와 function을 끝내세요. · 5 micro-work
출처
Source: Probeklausur.pdf / Probeklausur Musterlösung und Hinweise.pdf · 시험 p7–8 · 공식 해설 p8–11. 공식 답의 숫자와 course-specific datapath/FSM 가정은 변경하지 않았습니다.