---
schema_version: 1
exam_id: "sose26-probeklausur"
aufgabe: 3
unit_id: "3-5"
source_group_id: "3"
official_exam: true
official_solution: true
language: "ko"
---

# 3-5 — 안쪽 loop와 비교

> **학습 목표:** inner bound `n-i-1`, `&arr[j]`, 이웃 두 word, `arr[j] <= arr[j+1]` skip 조건을 순서대로 구현하고 trace한다.
>
> **왜 따로 배우는가:** bubble sort의 inner loop에는 off-by-one, Byte scaling, compare inversion이 한꺼번에 들어 있습니다. bound→주소→값→skip branch의 네 상태를 분리하면 out-of-bounds와 불필요한 swap을 동시에 막을 수 있습니다.
>
> **범위:** Aufgabe 3 · 8점 Aufgabe의 최소 학습 단위 · 시험 p7–8 · 공식 해설 p8–11

## 1. 문제 원문 (Deutsch)

이 unit은 공식 Teilaufgabe 또는 표의 한 행·한 access를 학습 가능한 최소 단위로 다시 나눈 것입니다. 아래 전사는 source group `3`의 공식 독일어 문제 원문이며, 페이지 이미지를 바로 뒤에 함께 두어 코드·표·도식을 대조할 수 있게 했습니다.

~~~text
Aufgabe 3: C in RISC-V übersetzen

void swap(int *arr, int i, int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void bubbleSort(int *arr, int n)
{
    for (int i = 0; i < n - 1; i++){
        for (int j = 0; j < n - i - 1; j++){
            if (arr[j] > arr[j + 1])
                swap(arr, j, j + 1);
        }
    }
}

Implementieren Sie die vorgestellten Funktionen in Assembler. Der von Ihnen geschriebenen Code muss die gleiche Funktionalität haben und möglichst nah an der Implementierung von C sein.

Hinweise:

• Es ist garantiert, dass das Array arr mindestens ein Element enthält.
• Variable n speichert die Länge von arr.
• Verwenden Sie innerhalb der Funktionen folgende Registerbelegung zur Speicherung der Variablen: s0 = arr, s1 = n, s2 = i, s3 = j
• Jede Funktion muss man als Unterprogramm betrachten.

Lösung:
~~~

![공식 시험 원문 — exam-p07.png](../../assets/exam-p07.png)

*공식 시험 원문: `exam-p07.png` · Probeklausur.pdf · PDF p.7*

![공식 시험 원문 — exam-p08.png](../../assets/exam-p08.png)

*공식 시험 원문: `exam-p08.png` · Probeklausur.pdf · PDF p.8*

### 이 unit에서 풀 항목

`j < n-i-1`과 `arr[j] > arr[j+1]`을 구현하세요.

## 2. 쉬운 한국어 해석

문제 3: C를 RISC-V로 번역하기

void swap(int *arr, int i, int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void bubbleSort(int *arr, int n)
{
    for (int i = 0; i < n - 1; i++){
        for (int j = 0; j < n - i - 1; j++){
            if (arr[j] > arr[j + 1])
                swap(arr, j, j + 1);
        }
    }
}

위에 제시된 함수들을 어셈블리로 구현하시오. 작성한 코드는 C 구현과 동일한 기능을 가져야 하며, 가능한 한 C 구현에 가깝게 작성해야 한다.

주의사항:

• 배열 arr에는 적어도 한 개의 원소가 있음이 보장된다.
• 변수 n에는 배열 arr의 길이가 저장되어 있다.
• 함수 안에서 변수를 저장할 때 다음 레지스터 배치를 사용하시오: s0 = arr, s1 = n, s2 = i, s3 = j.
• 각 함수는 하나의 서브루틴으로 간주해야 한다.

답안:

### 이 unit에 해당하는 최소 작업

`j < n-i-1`과 `arr[j] > arr[j+1]`을 구현하세요.

이 문제에서 최종 결과만 맞히는 것보다 중요한 것은 `3-5`에 필요한 중간 판단을 답안지에 남기는 것입니다.

## 3. 무엇을 묻는 문제인가

### 공식 문제의 요구사항

- C 함수 swap을 동일한 동작의 RISC-V 어셈블리 서브루틴으로 구현한다.
- C 함수 bubbleSort를 중첩 반복문, 조건문, swap 호출까지 보존하여 RISC-V 어셈블리로 구현한다.
- 배열 원소 주소 계산, 함수 호출, 레지스터 보존, 반환 동작을 포함해 C 의미와 RISC-V 호출 규약을 함께 만족시킨다.

### 조건과 제약

- arr에는 최소 한 원소가 있다.
- n은 arr의 길이이다.
- 함수 내부 변수 배치는 s0=arr, s1=n, s2=i, s3=j로 지정되어 있다.
- swap과 bubbleSort를 각각 독립적인 Unterprogramm으로 취급한다.
- 작성한 어셈블리의 기능은 C와 같아야 하며 가능한 한 C 구조에 가깝게 작성해야 한다.

### 원문 오탈자·도식 관련 주의

- 시험 PDF p7에 문제와 코드가 있고 p8은 'Lösung:'만 있는 빈 답안 페이지이다.
- 원문의 'Jede Funktion muss man als Unterprogramm betrachten.'는 다소 어색한 독일어 표현이지만 의미를 수정하지 않고 보존했다.
- [문제–공식 해설 차이] 원문은 'innerhalb der Funktionen'에서 s0=arr, s1=n, s2=i, s3=j를 사용하라고 읽히지만, 공식 swap 해설은 a/t-register만 사용하고 이 지정 배치를 bubbleSort의 장기 상태에 적용한다. 공식 코드는 ABI상 유효하나 문구를 문자 그대로 적용한 답과는 차이가 있다.
- 코드 들여쓰기는 PDF 시각 확인 결과에 맞춰 정리했으며 식, 조건, 레지스터 이름과 상수는 변경하지 않았다.

### 도식 시각 확인 상태

- **도식 의존 여부:** 이 최소 unit의 핵심 판정은 텍스트·수식·코드로 재현할 수 있습니다.
- **공식 페이지 상태:** exam-p07.png, exam-p08.png, solution-p08.png, solution-p10.png가 원문 대조용으로 렌더되어 연결되어 있습니다.

### 이 unit의 학습 목표

- **관찰 가능한 목표:** inner bound `n-i-1`, `&arr[j]`, 이웃 두 word, `arr[j] <= arr[j+1]` skip 조건을 순서대로 구현하고 trace한다.
- **출제 의도:** bubble sort의 inner loop에는 off-by-one, Byte scaling, compare inversion이 한꺼번에 들어 있습니다. bound→주소→값→skip branch의 네 상태를 분리하면 out-of-bounds와 불필요한 swap을 동시에 막을 수 있습니다.
- **공식 근거 범위:** SoSe26 Probeklausur 시험 p7–8 Aufgabe 3의 inner loop·이웃 비교와 공식 해설 p10의 bound/address/load/ble 구현 범위.
- **Aufgabe 공통 선수지식:** C variable을 register에 배치하고, array index를 byte offset으로 바꾸고, loop 조건을 ‘끝나면 탈출’ branch로 뒤집습니다. 다른 함수를 부르면 ra와 오래 살아야 하는 값을 stack/s-register로 보호합니다.

## 4. 선수 개념과 핵심 용어

### inner bound

- **뜻:** 현재 outer iteration에서 j가 가질 수 있는 exclusive upper bound `n-i-1`입니다.
- **이 문제에서:** `j>=bound`이면 outer_inc로 나가도록 비교합니다.

### adjacent elements

- **뜻:** array에서 index가 1 차이 나는 `arr[j]`와 `arr[j+1]`입니다.
- **이 문제에서:** 같은 base address에서 offset 0과 4로 두 word를 load합니다.

### ble

- **뜻:** 첫 signed operand가 둘째보다 작거나 같으면 branch하는 pseudo instruction입니다.
- **이 문제에서:** 이미 오름차순인 `arr[j]<=arr[j+1]`이면 swap을 건너뜁니다.

### off-by-one

- **뜻:** loop bound에서 1이 빠지거나 더해져 한 iteration을 누락하거나 범위를 넘는 오류입니다.
- **이 문제에서:** `j+1`이 최대 n-1이 되도록 j의 bound가 `n-i-1`인지 검산합니다.

### 이 문제에 적용할 풀이 규칙

### 규칙 1. exclusive bound 규칙

inner body는 `j < n-i-1`일 때만 실행하므로 반대 조건 `j>=n-i-1`에서 종료합니다.

- **시험지에 남길 것:** `bound=n-i-1`, `valid j=0…bound-1`을 씁니다.

### 규칙 2. 이웃 주소 재사용 규칙

`int` 이웃은 4 Byte 차이므로 `&arr[j]`를 한 번 만든 뒤 offset 0과 4로 load하면 됩니다.

- **시험지에 남길 것:** `t1=&arr[j]`, `0(t1)=arr[j]`, `4(t1)=arr[j+1]`을 표시합니다.

### 규칙 3. swap 필요 조건 분리

오름차순에서는 왼쪽 값이 더 클 때만 swap하므로 `left<=right`이면 swap을 skip합니다.

- **시험지에 남길 것:** `swap iff left>right; skip iff left<=right` 두 줄을 씁니다.

### 공식 문제 전에 푸는 작은 유사 예제

**문제:** n=6, i=2, j=1, base=`0x1000`, arr[1]=9, arr[2]=4일 때 inner guard, 주소, 비교 결과를 trace하세요.

**주어진 것**

- s1=n=6, s2=i=2, s3=j=1입니다.
- `int`는 4 Byte입니다.

### 예제 단계 1. inner bound를 계산하고 j와 비교합니다.

- **왜:** memory access 전에 j와 j+1이 유효한지 확인합니다.
- **종이에:** `bound=6-2-1=3; 1>=3 false → continue`

### 예제 단계 2. `&arr[1]`과 이웃 주소를 계산합니다.

- **왜:** base+scaled index에서 두 word를 읽어야 합니다.
- **종이에:** `t1=0x1000+1×4=0x1004; neighbor=0x1008`

### 예제 단계 3. 두 값을 load해 skip 조건을 검사합니다.

- **왜:** 9<=4가 거짓이므로 현재 순서가 잘못되어 swap이 필요합니다.
- **종이에:** `t2=9, t3=4; ble 9,4 false`

### 예제 단계 4. control-flow 결론을 씁니다.

- **왜:** ble가 taken되지 않으면 다음 instruction인 swap call로 fall-through합니다.
- **종이에:** `fall-through → swap(arr,1,2)`

**예제 정답:** bound=3이라 body를 실행하며 주소는 `0x1004`와 `0x1008`입니다. 9<=4가 거짓이므로 swap을 호출해야 합니다.

**독립 검산:** swap 후 두 값이 4,9가 되어 오름차순 이웃 조건을 만족하는지 확인합니다.

## 5. 공식 정답 요약

**공식 결론:** `sub t0,s1,s2; addi t0,t0,-1; bge s3,t0,outer_inc; slli t1,s3,2; add t1,s0,t1; lw t2,0(t1); lw t3,4(t1); ble t2,t3,inner_inc`.

### 시험지 문장별 정답 해설

아래는 시험지의 항목 순서를 그대로 유지합니다. 각 항목에서 원문 → 한국어 번역 → 정답 → 판단 근거 → 실제로 쓸 답을 바로 이어서 읽으세요.



### 현재 소문제의 요구·판단·답을 한 흐름으로 연결

### `3-5`에서 정확히 답할 대상

- **시험지가 요구하는 답:** `j < n-i-1`과 `arr[j] > arr[j+1]`을 구현하세요.
- **이 소문제의 공식 답:** `sub t0,s1,s2; addi t0,t0,-1; bge s3,t0,outer_inc; slli t1,s3,2; add t1,s0,t1; lw t2,0(t1); lw t3,4(t1); ble t2,t3,inner_inc`.

### 판단 1. 현재 inner bound `n-i-1`을 t0에 계산합니다.

- **왜:** 각 outer iteration마다 정렬된 suffix가 하나씩 늘어나므로 검사 범위가 i에 따라 줄어듭니다.
- **이 판단에서 답안지에 남길 것:** `sub t0,s1,s2; addi t0,t0,-1  # t0=n-i-1`

### 판단 2. j>=bound이면 outer_inc로 탈출합니다.

- **왜:** 유효 조건 `j<bound`의 부정이며 더 이상 비교할 이웃 쌍이 없음을 나타냅니다.
- **이 판단에서 답안지에 남길 것:** `bge s3,t0,outer_inc  # if j>=n-i-1 exit inner`

### 판단 3. j를 4배하고 arr base를 더해 `&arr[j]`를 만듭니다.

- **왜:** RISC-V memory address는 Byte 단위이며 int index는 4-Byte scale이 필요합니다.
- **이 판단에서 답안지에 남길 것:** `slli t1,s3,2; add t1,s0,t1  # t1=&arr[j]`

### 판단 4. `0(t1)`과 `4(t1)`에서 이웃 값을 load합니다.

- **왜:** `arr[j+1]`는 int 하나 뒤이므로 새 index/address 계산 없이 현재 주소+4를 사용할 수 있습니다.
- **이 판단에서 답안지에 남길 것:** `lw t2,0(t1)  # left; lw t3,4(t1)  # right`

### 판단 5. left<=right이면 inner_inc로 가서 swap을 건너뜁니다.

- **왜:** 오름차순에서 이미 올바른 이웃은 교환할 필요가 없고, left>right일 때만 call로 fall-through해야 합니다.
- **이 판단에서 답안지에 남길 것:** `ble t2,t3,inner_inc  # skip swap if ordered`

### 위 판단이 최종 답으로 이어지는 이유

매 반복에서 현재 upper bound를 계산하고, 이웃 두 word는 같은 base address에서 offset 0과 4로 읽을 수 있습니다.

### 답안 작성 시 주의

`j+1` 주소를 다시 처음부터 계산할 필요 없이 현재 주소+4를 쓸 수 있습니다.

![공식 Musterlösung/Hinweise — solution-p08.png](../../assets/solution-p08.png)

*공식 Musterlösung/Hinweise: `solution-p08.png` · Probeklausur Musterlösung und Hinweise.pdf · PDF p.8*

![공식 Musterlösung/Hinweise — solution-p10.png](../../assets/solution-p10.png)

*공식 Musterlösung/Hinweise: `solution-p10.png` · Probeklausur Musterlösung und Hinweise.pdf · PDF p.10*

## 6. 풀이 전략

1. n-i-1을 t0에 계산합니다.
2. j>=bound이면 outer_inc로 갑니다.
3. j×4와 arr base로 &arr[j]를 만듭니다.
4. 0(t1), 4(t1)에서 이웃 값을 읽습니다.
5. arr[j]<=arr[j+1]이면 swap을 건너뜁니다.

## 7. 단계별 상세 풀이

### 단계 1. 현재 inner bound `n-i-1`을 t0에 계산합니다.

- **이유:** 각 outer iteration마다 정렬된 suffix가 하나씩 늘어나므로 검사 범위가 i에 따라 줄어듭니다.
- **종이에 남길 것:** `sub t0,s1,s2; addi t0,t0,-1  # t0=n-i-1`
- **완료 기준:** t0가 n-i가 아니라 n-i-1로 표시되어 있습니다.
- **막힐 때 힌트:** 먼저 n-i를 구한 뒤 1을 빼세요.
- **가장 흔한 첫 오류:** `n-i`까지만 계산해 j+1이 array 끝을 넘을 수 있게 만드는 것입니다.

### 단계 2. j>=bound이면 outer_inc로 탈출합니다.

- **이유:** 유효 조건 `j<bound`의 부정이며 더 이상 비교할 이웃 쌍이 없음을 나타냅니다.
- **종이에 남길 것:** `bge s3,t0,outer_inc  # if j>=n-i-1 exit inner`
- **완료 기준:** source s3=j, t0=bound와 target outer_inc가 맞습니다.
- **막힐 때 힌트:** j가 bound와 같아지는 순간 `arr[j+1]`이 현재 범위를 벗어납니다.
- **가장 흔한 첫 오류:** `bgt`만 사용해 j=bound에서도 body를 한 번 더 실행하는 것입니다.

### 단계 3. j를 4배하고 arr base를 더해 `&arr[j]`를 만듭니다.

- **이유:** RISC-V memory address는 Byte 단위이며 int index는 4-Byte scale이 필요합니다.
- **종이에 남길 것:** `slli t1,s3,2; add t1,s0,t1  # t1=&arr[j]`
- **완료 기준:** t1의 최종 의미가 scaled offset이 아니라 absolute address입니다.
- **막힐 때 힌트:** s0에는 Prolog에서 보존한 arr base가 있습니다.
- **가장 흔한 첫 오류:** s3를 그대로 s0에 더하거나 s0 자체를 destination으로 덮는 것입니다.

### 단계 4. `0(t1)`과 `4(t1)`에서 이웃 값을 load합니다.

- **이유:** `arr[j+1]`는 int 하나 뒤이므로 새 index/address 계산 없이 현재 주소+4를 사용할 수 있습니다.
- **종이에 남길 것:** `lw t2,0(t1)  # left; lw t3,4(t1)  # right`
- **완료 기준:** t2=arr[j], t3=arr[j+1]의 방향이 표시되어 있습니다.
- **막힐 때 힌트:** 두 번째 offset은 index 1이 아니라 Byte 4입니다.
- **가장 흔한 첫 오류:** `lw t3,1(t1)`로 한 Byte 뒤에서 misaligned word를 읽는 것입니다.

### 단계 5. left<=right이면 inner_inc로 가서 swap을 건너뜁니다.

- **이유:** 오름차순에서 이미 올바른 이웃은 교환할 필요가 없고, left>right일 때만 call로 fall-through해야 합니다.
- **종이에 남길 것:** `ble t2,t3,inner_inc  # skip swap if ordered`
- **완료 기준:** taken=skip, not taken=swap이라는 control-flow가 값 조건과 일치합니다.
- **막힐 때 힌트:** swap 조건 `left>right`의 반대를 branch 조건으로 사용하세요.
- **가장 흔한 첫 오류:** `bge` 방향을 잘못 사용해 정렬된 쌍을 swap하고 역순 쌍을 건너뛰는 것입니다.

## 8. 문제와 공식 해설의 비교·검증

- **문제가 요구하는 것:** `j < n-i-1`과 `arr[j] > arr[j+1]`을 구현하세요.
- **공식 해설이 제시하는 결론:** `sub t0,s1,s2; addi t0,t0,-1; bge s3,t0,outer_inc; slli t1,s3,2; add t1,s0,t1; lw t2,0(t1); lw t3,4(t1); ble t2,t3,inner_inc`.
- **결론을 재현하는 핵심 논리:** 매 반복에서 현재 upper bound를 계산하고, 이웃 두 word는 같은 base address에서 offset 0과 4로 읽을 수 있습니다.
- **검증 방법:** 위 micro-step의 `종이에 남길 것`을 순서대로 만들고 각 `완료 기준`을 확인합니다. 최종 산출물이 공식 결론과 같은지 대조합니다.
- **전제와 주의 범위:** `j+1` 주소를 다시 처음부터 계산할 필요 없이 현재 주소+4를 쓸 수 있습니다.
- **채택할 시험 답:** 이 가이드에서는 공식 Musterlösung의 결론을 시험 답으로 유지하며, 일반 ISA 또는 다른 구현과 달라질 수 있는 부분은 위 전제와 주의 범위에서 분리합니다.

## 9. 시험장에서 쓸 최종 답안

`sub t0,s1,s2; addi t0,t0,-1; bge s3,t0,outer_inc; slli t1,s3,2; add t1,s0,t1; lw t2,0(t1); lw t3,4(t1); ble t2,t3,inner_inc`.

아래는 이 unit의 register/label 전제를 모두 포함한 완성 답안입니다. 현재 unit에서 다룬 block을 위 micro-step과 대조하세요.

```asm
swap:
    slli t0, a1, 2
    add  t0, a0, t0
    lw   t1, 0(t0)
    slli t2, a2, 2
    add  t2, a0, t2
    lw   t3, 0(t2)
    sw   t3, 0(t0)
    sw   t1, 0(t2)
    ret

bubbleSort:
    addi sp, sp, -32
    sw   ra, 0(sp)
    sw   s0, 4(sp)
    sw   s1, 8(sp)
    sw   s2, 12(sp)
    sw   s3, 16(sp)
    mv   s0, a0
    mv   s1, a1
    addi s2, zero, 0

outer_loop:
    addi t0, s1, -1
    bge  s2, t0, done
    li   s3, 0

inner_loop:
    sub  t0, s1, s2
    addi t0, t0, -1
    bge  s3, t0, outer_inc
    slli t1, s3, 2
    add  t1, s0, t1
    lw   t2, 0(t1)
    lw   t3, 4(t1)
    ble  t2, t3, inner_inc
    mv   a0, s0
    mv   a1, s3
    addi a2, s3, 1
    jal  ra, swap

inner_inc:
    addi s3, s3, 1
    j    inner_loop

outer_inc:
    addi s2, s2, 1
    j    outer_loop

done:
    lw   ra, 0(sp)
    lw   s0, 4(sp)
    lw   s1, 8(sp)
    lw   s2, 12(sp)
    lw   s3, 16(sp)
    addi sp, sp, 32
    ret
```

답안지에는 결과만 쓰지 말고, 7절의 중간 산출물 가운데 판정을 증명하는 식·bit field·register 상태·cycle·cache 상태를 함께 남기세요.

## 10. 자주 하는 실수와 검산 체크리스트

### 대표 실수

- `j+1` 주소를 다시 처음부터 계산할 필요 없이 현재 주소+4를 쓸 수 있습니다.
- `n-i`까지만 계산해 j+1이 array 끝을 넘을 수 있게 만드는 것입니다.
- `bgt`만 사용해 j=bound에서도 body를 한 번 더 실행하는 것입니다.
- s3를 그대로 s0에 더하거나 s0 자체를 destination으로 덮는 것입니다.
- `lw t3,1(t1)`로 한 Byte 뒤에서 misaligned word를 읽는 것입니다.
- `bge` 방향을 잘못 사용해 정렬된 쌍을 swap하고 역순 쌍을 건너뛰는 것입니다.

### 빠른 self-check

- **회상 질문:** 왜 bubble sort의 안쪽 upper bound는 반복마다 1씩 줄어드나요?
- [ ] n, i, j 값을 주면 memory access 전에 inner guard가 통과하는지 trace할 수 있다.
- [ ] left/right 값에 따라 ble의 taken 여부와 swap 실행 여부를 일관되게 판정할 수 있다.

## 11. 짧은 확인 문제와 전이 연습

### 개념 재구성

**문제:** bubble sort inner iteration 하나를 bound check, address, two loads, skip condition의 네 상태로 복원하고 각 register 의미를 쓰세요.

**힌트:** t0, t1, t2, t3이 각각 무엇을 담는지 고정하세요.

<details>
<summary>정답과 채점 기준 보기</summary>

**모범 답:** `t0=n-i-1`을 만들고 `j>=t0`이면 종료합니다. `t1=base+j×4=&arr[j]`를 만들고 `t2=0(t1)=left`, `t3=4(t1)=right`를 load합니다. `left<=right`이면 swap을 skip하고, 아니면 swap을 호출합니다.

**채점 기준**
  - t0=n-i-1
  - j>=t0
  - t1=base+j×4
  - &arr[j]
  - t2=0(t1)=left
  - t3=4(t1)=right
  - left<=right
  - skip
  - swap

</details>

### 변형 문제

**문제:** n=5, i=1, j=2이고 arr[2]=3, arr[3]=7이다. inner bound, guard 결과, load offset, ble 결과를 계산하세요.

**힌트:** bound는 exclusive이며 j와 같아도 종료합니다.

<details>
<summary>정답과 채점 기준 보기</summary>

**모범 답:** `bound=5-1-1=3`, `j=2<3`이므로 body를 실행합니다. `&arr[2]`에서 offset 0과 4로 3과 7을 load하고 `3<=7`이 참이라 ble가 taken되어 swap을 skip합니다.

**채점 기준**
  - bound=5-1-1=3
  - j=2<3
  - offset 0
  - 4
  - 3
  - 7
  - 3<=7
  - taken
  - skip

</details>

### 오답 진단

**문제:** 학생 code는 bound를 `n-i`로 두고 j=bound-1에서도 `arr[j+1]`을 읽습니다. n=5, i=0에서 첫 off-by-one과 접근 index를 계산해 고치세요.

**힌트:** 올바른 마지막 j와 잘못된 마지막 j를 각각 구하세요.

<details>
<summary>정답과 채점 기준 보기</summary>

**모범 답:** 첫 오류는 bound에서 마지막 -1을 빠뜨린 것입니다. 잘못된 bound=5이면 j=4까지 body가 가능해 `arr[5]`를 읽어 out-of-bounds입니다. 올바른 bound는 `n-i-1=4`이고 valid j는 0…3이라 마지막 이웃은 `arr[4]`입니다.

**채점 기준**
  - 마지막 -1
  - bound=5
  - j=4
  - arr[5]
  - out-of-bounds
  - n-i-1=4
  - 0…3
  - arr[4]

</details>

## 12. 근거 자료

- `[문제 출처] current:Probeklausur.pdf` — 시험 p7–8 · 공식 해설 p8–11
- `[공식 해설] current:Probeklausur Musterlösung und Hinweise.pdf` — 시험 p7–8 · 공식 해설 p8–11
- `[정확한 원문 group] 3` — 시험 p.7, p.8 · 공식 해설 p.8, p.9, p.10, p.11
- `[소문항 범위] SoSe26 Probeklausur 시험 p7–8 Aufgabe 3의 inner loop·이웃 비교와 공식 해설 p10의 bound/address/load/ble 구현 범위.`
- `[개념 근거 · file-level] current:Vorlesung/Rechnerorganisation - Teil 1.pdf` — RISC-V assembler와 C translation
- `[개념 근거 · file-level] current:Uebung/Übung 2 Musterlösung/Rechnerorganisation_Übung2_Lösung.pdf` — assembler programming과 array access
- `[개념 근거 · file-level] current:Uebung/Übung 3 Musterlösung.pdf` — calling convention과 stack frame
- `[개념 근거 · file-level] current:Uebung/RISC-V Reference.pdf` — instruction과 ABI register 이름

### 이 파일에서 직접 대조한 공식 이미지

- `exam-p07.png` — Probeklausur.pdf · PDF p.7
- `exam-p08.png` — Probeklausur.pdf · PDF p.8
- `solution-p08.png` — Probeklausur Musterlösung und Hinweise.pdf · PDF p.8
- `solution-p10.png` — Probeklausur Musterlösung und Hinweise.pdf · PDF p.10

정확한 강의 슬라이드 한 페이지를 확정하지 못한 개념 자료는 `file-level`로 표시했습니다. 페이지 번호를 추측해서 만들지 않았습니다.
