[CSAPP 3장 완전 정복] 3.8.5 동적 배열(VLA), 주소 계산은 어떻게 달라질까?
·
크래프톤 정글/컴퓨터구조(CSAPP)
동적 배열(VLA), 주소 계산은 어떻게 달라질까?이전 포스트에서는 배열의 크기가 고정되어 있는 경우를 다뤘다면, 이번에는 크기가 런타임에 결정되는 동적 배열(Variable-Length Array)을 어셈블리어에서 어떻게 접근하는지 알아보겠습니다. 동적 배열은 C99부터 지원되는 기능으로, 배열의 크기를 컴파일 타임이 아니라 실행 중에 결정할 수 있습니다.  예제 코드: 동적 2차원 배열void set_val(int n, int A[n][n], int i, int j, int val) { A[i][j] = val;}여기서 배열 A는 크기가 n x n으로, 호출 시점에 그 크기가 결정됩니다. 그렇다면 A[i][j]는 메모리에서 어떤 위치를 의미할까요?주소 = A + (i * n + j) * 4이 계..
[CSAPP 3장 완전 정복] 3.8 배열, 포인터, 주소 계산의 모든 것
·
크래프톤 정글/컴퓨터구조(CSAPP)
배열, 포인터, 주소 계산의 모든 것이번 포스트에서는 C 코드에서 자주 사용하는 배열이 어셈블리에서는 어떻게 주소를 계산하고 접근하는지를 살펴볼 예정인데요. 포인터 연산, 인덱스 계산, 메모리 접근까지 모두 직관적인 매핑 방식으로 이해해보겠습니다.  어셈블리의 배열 접근 방법, 주소 계산int A[5];int x = A[3];이 단순한 배열 접근은 어셈블리어에서는 다음과 같은 주소 계산으로 바뀝니다.movl A+12, %eax이때 int는 4바이트이므로, A[3]은 A + 3 * 4 = A + 12 위치에 있는 값이 됩니다.  주소 계산 공식: D(Rb, Ri, S)주소 계산 공식은 3.4절에서 메모리 접근 방식에 대해 설명할 때 소개해드린 적 있는데요. 그때 배열 접근에서도 이 공식이 사용된다고 말씀드..
[CSAPP 3장 완전 정복] 3.7 함수 호출, 스택, 레지스터의 삼각관계
·
크래프톤 정글/컴퓨터구조(CSAPP)
함수 호출, 스택, 레지스터의 삼각관계C에서의 function(a, b) 한 줄은 어셈블리어 세계에서는 꽤 복잡한 과정으로 번역됩니다. 이번 3.7절은 바로 그 "함수 호출의 내부 구조", 즉 스택을 어떻게 쓰고, 레지스터를 어떻게 관리하며, 인자와 반환값은 어떻게 주고받는지를 설명합니다. 이번 포스트부터는 우리가 배운 어셈블리 구조를 바탕으로, 함수 호출, 조건문, 반복문 같은 C 코드의 익숙한 구문들이 어셈블리에서 어떻게 구현되는지를 직접 매핑해보는 방식으로 진행할 예정입니다.  C 함수 호출, 내부적으로 어떤 일이 벌어질까?int sum(int a, int b) { return a + b;}int main() { int x = sum(3, 4);}main에서 sum이 호출되어 반환값이 변..
[CSAPP 3장 완전 정복] 3.4 메모리와 레지스터, 정보를 어떻게 읽고 쓸까?
·
크래프톤 정글/컴퓨터구조(CSAPP)
메모리와 레지스터, 정보를 어떻게 읽고 쓸까?컴파일된 C 프로그램이 실행될 때, 대부분의 연산은 레지스터와 메모리 사이의 정보 이동으로 이루어지는데요. 이번 절 3.4는 바로 그 정보 접근의 핵심 메커니즘, 즉 어셈블리어에서 값을 어디서 읽고, 어디로 저장하는지를 표현하는 방식을 설명하고 있습니다. 이 절을 제대로 이해하면, 이후에 나오는 배열, 구조체, 함수 호출, 스택 프레임 등 모든 개념을 더 쉽게 받아들일 수 있게 됩니다.  기본 주소 계산 방식 (Address Computation)어셈블리어에서 가장 자주 사용되는 명령어 중 하나는 mov인데요. 이는 어떤 값(레지스터/메모리/상수)을 다른 장소로 복사하는 명령입니다. 이때 메모리에서 값을 읽어오거나 쓸 때는 주소 계산이 필요한데, x86-64에..
[CSAPP 3장 완전 정복] x86-64 어셈블리 필수 배경지식 핵심 정리
·
크래프톤 정글/컴퓨터구조(CSAPP)
x86-64 어셈블리 필수 배경지식 핵심 정리본격적으로 3.4절을 살펴보기 전에, 아직 어셈블리에 익숙하지 않은 분들도 있을 수 있습니다. 그래서 먼저 어셈블리를 이해하는 데 필요한 핵심 배경지식을 간단히 살펴보며, 실제로 어셈블리 코드를 해석할 수 있는 준비를 해보겠습니다. 어셈블리를 이해하기 위한 핵심 키워드레지스터주소값 vs 참조함수 호출 흐름caller / callee 개념메모리와 연산의 관계 레지스터란? 그리고 왜 중요한가레지스터(Register)는 CPU 내부의 초고속 데이터 저장 공간입니다. 대부분의 연산은 레지스터 간, 또는 레지스터와 메모리 간에서 이루어지지요. 다만 레지스터 개수는 한정되어 있기 때문에, 누가 언제 어떤 레지스터를 책임지고 보존하느냐가 중요합니다. x86-64의 주요..
[CSAPP 3장 완전 정복] 3.5 기계 수준의 연산, 어떻게 작동할까?
·
크래프톤 정글/컴퓨터구조(CSAPP)
기계 수준의 연산, 어떻게 작동할까?C 코드에서 우리가 아무렇지 않게 사용하는 +, -, *, &, | 등의 연산자들은 기계 수준에서 명령어 형태로 정확히 변환됩니다. 이번 절에서는 산술 및 논리 연산을 수행하는 명령어들이 어셈블리어에서 어떤 방식으로 표현되는지 간략히 알아보겠습니다. 산술 연산 명령어명령어설명add두 값을 더함sub두 값을 뺌imul정수 곱셈inc / dec1 증가 / 감소neg부호 반전 (0 - x)예시) addq %rax, %rdx → %rdx = %rdx + %rax 즉시값을 사용하는 연산일반적인 연산 외에도, 즉시값(Immediate Value)을 이용한 연산도 가능합니다.addq $10, %rax ; %rax에 10 더하기즉시값은 $ 기호로 표현되며, 레지스터나 메..
[CSAPP 3장 완전 정복] 3.3 데이터는 메모리에 어떻게 저장될까?
·
크래프톤 정글/컴퓨터구조(CSAPP)
데이터는 메모리에 어떻게 저장될까?우리가 사용하는 정수, 실수, 포인터 같은 값들은 모두 메모리의 바이트 배열로 저장됩니다. 이번 3.3절은 이 값들이 실제로 어떻게 저장되고, 어떤 크기를 가지며, 또 어떤 의미를 가지는지를 알려줍니다. C의 데이터 타입과 바이트 크기x86-64 시스템에서 각 기본 타입은 아래와 같은 바이트 수를 차지합니다.데이터 타입바이트 수char1 byteshort 2 bytesint4 byteslong 8 bytes (x86-64 기준) float4 bytesdouble8 bytespointer8 bytes (x86-64 기준)이런 크기를 알아두는 이유는, 이후 포인터 연산, 메모리 접근, 구조체 해석에서 각 타입이 얼마만큼의 메모리 공간을 차지하는지를 정확히 파악해야 하기 때..
[CSAPP 3장 완전 정복] 3.2 어셈블리 명령어는 어떻게 저장될까?
·
크래프톤 정글/컴퓨터구조(CSAPP)
어셈블리 명령어는 어떻게 저장될까?C 언어로 작성한 코드 한 줄이 어셈블리 코드로 바뀌고, 그 어셈블리 코드는 다시 바이너리 머신 코드(기계어)로 변환된다는 얘기를 한 번쯤 들어본 적 있으실 것 같습니다. 이번 3.2절에서는 바로 그 과정을 개략적으로 보여주는데요. 즉, "어셈블리어는 실제로 메모리 안에 어떻게 저장될까?"라는 질문에 대한 첫 번째 답을 다루고 있습니다. C 코드가 기계어로 실행되기까지ISA: 기계어의 설계 기준C 코드가 어셈블리로, 그리고 다시 기계어로 번역된다는 말은 단순히 코드 형식이 바뀐다는 의미를 넘어서, 이 모든 명령어들이 ISA(Instruction Set Architecture)라는 체계에 따라 정의되어 있다는 뜻입니다. ISA는 어떤 명령어들이 존재하는지, 각각이 어떤 ..