[컴퓨터 시스템] 12. 배열과 구조체는 어셈블리에서 왜 주소 계산이 될까
고수준 언어에서는 `arr[i]`나 `s.field`가 자연스러운 문법처럼 보입니다. 하지만 저수준으로 내려오면 결국 둘 다 '기준 주소에서 얼마나 떨어진 위치를 읽고 쓰는가'라는 주소 계산 문제로 보이기 시작합니다.
이번 글은 배열, 포인터, 구조체를 다시 한 번 어셈블리 관점으로 묶어 보면서, 왜 메모리 배치 감각이 중요했는지 연결합니다.
- 배열 인덱싱이 주소 계산으로 보이는 이유
- 구조체 필드 접근이 offset 문제로 읽히는 이유
- 자료형 크기가 주소 계산에 왜 들어가는지
- 포인터와 배열 감각이 여기서 어떻게 다시 쓰이는지
- 메모리 레이아웃을 눈으로 읽는 연습 문제
1. 배열 접근은 기준 주소 + 간격 계산으로 바뀐다
배열은 연속된 메모리라는 점이 핵심입니다. 그래서 `arr[i]`는 추상적인 문법이 아니라 기준 주소에서 i칸 떨어진 위치를 찾는 계산으로 이해할 수 있습니다.
여기서 중요한 것은 i만이 아니라 원소 하나의 크기입니다. int 배열과 char 배열은 같은 i라도 실제 주소 간격이 다릅니다.
| 표현 | 저수준 질문 |
|---|---|
| arr[i] | 기준 주소에서 i * 원소 크기만큼 떨어진 곳은 어디인가 |
| p + i | 현재 주소에서 몇 바이트 움직여야 하나 |
2. 구조체 필드는 이름이 아니라 offset으로 보인다
구조체는 필드 이름으로 접근하지만, 메모리 안에서는 결국 각 필드가 시작 기준에서 몇 바이트 떨어져 있는지가 중요합니다. 그래서 구조체 접근은 기준 주소 + 필드별 offset으로 읽을 수 있습니다.
즉 `s.age` 같은 표현도 저수준에서는 's 시작 주소에서 age 필드 offset을 더한 위치'라는 질문으로 풀립니다.
| 구조체 요소 | 저수준 감각 |
|---|---|
| 구조체 시작 | base address |
| 필드 위치 | field offset |
| 필드 접근 | base + offset 읽기/쓰기 |
3. 자료형 크기가 주소 계산에 끼어드는 이유
초반에는 인덱스만 바뀌는 것처럼 보이지만, 실제 주소 계산에서는 자료형 크기가 꼭 들어갑니다. 4바이트 int 배열에서 다음 원소는 1바이트 뒤가 아니라 4바이트 뒤에 있기 때문입니다.
그래서 배열과 포인터를 읽을 때는 항상 '이 타입 하나가 몇 바이트인가'를 함께 떠올리는 습관이 좋습니다.
4. 조금 더 현실적인 코드 예제를 보자
이 코드에서 저수준 질문은 두 가지입니다. `p->y`는 구조체 시작 주소에서 어느 offset을 읽는가, `arr[i]`는 기준 주소에서 얼마만큼 이동한 뒤 읽는가입니다.
struct Point {
int x;
int y;
};
int sum(struct Point *p, int i, int *arr) {
return p->y + arr[i];
}5. 직접 해볼 문제: 메모리 레이아웃을 글로 설명해 보자
어셈블리 문법을 몰라도 충분히 풀 수 있는 문제입니다. 핵심은 이름을 주소 계산 문제로 바꾸는 연습입니다.
이번 글에서 기억할 것
스스로 점검
다음 글 예고
다음 글에서는 x86-64와 ARM64를 비교하면서, ISA가 달라도 우리가 붙잡아야 할 핵심 공통 감각이 무엇인지 정리합니다.
'학습 자료 글 > 컴퓨터시스템' 카테고리의 다른 글
| 컴퓨터시스템 기초 14. 메모리 계층은 왜 프로그램 속도를 바꿀까 (0) | 2026.03.31 |
|---|---|
| 컴퓨터시스템 기초 13. x86-64와 ARM64는 무엇이 같고 다를까 (0) | 2026.03.31 |
| 컴퓨터시스템 기초 11. 레지스터와 스택 프레임은 함수 호출을 어떻게 드러낼까 (0) | 2026.03.31 |
| 컴퓨터시스템 기초 10. 어셈블리는 왜 C와 하드웨어 사이의 번역본일까 (0) | 2026.03.31 |
| 컴퓨터시스템 기초 9. CPU는 명령을 어떤 단계로 실행할까 (0) | 2026.03.31 |