컴퓨터 메인보드 위에는 CPU 칩, RAM(메모리) 칩, 하드디스크/키보드 같은 I/O 장치들이 장착되어 있습니다. 이 칩들 사이에 0V(전압 없음=0)와 3.3V(전압 있음=1)의 전기 신호를 주고받기 위해 연결된 수십 가닥의 미세한 구리 전선 묶음을 시스템 버스라고 부릅니다.
int x = 10;
int *p = &x;
x 변수: RAM의 1000번지부터 1003번지까지의 4바이트 공간에 2진수로 숫자 10이 들어 있습니다.&x: x가 위치한 시작 주소 번호인 숫자 1000을 뜻합니다.p 포인터 변수: RAM의 2000번지부터 2007번지까지의 8바이트 공간이며, 그 안에 데이터 내용물로 숫자 1000이 저장됩니다.*p: p 변수 안에 들어있는 숫자 1000번지로 직접 가서 거기에 저장된 숫자 10을 읽거나 변경하는 동작입니다.우리가 작성한 C 코드는 컴파일되면 0과 1의 기계어 바이너리로 바뀌어 메모리의 코드 영역(Text Segment)에 순서대로 배치됩니다.
int add(int a, int b) { return a + b; }
int (*fp)(int, int) = add;
add 함수는 메모리 어딘가(예: 5000번지)에 적재된 기계어 코드들의 묶음입니다.fp 변수는 그 add 함수의 시작 주소 번호인 숫자 5000을 저장하는 8바이트 변수입니다.fp(10, 20)을 실행하면 CPU는 명령어 포인터를 5000번지로 이동시켜 add 함수의 기계어를 실행합니다.함수를 호출할 때 넘겨주는 값(인자)들은 메모리가 아니라 CPU 내부의 임시 고속 저장소인 레지스터에 아래 순서대로 들어갑니다:
1번째 인자: %rdi 레지스터
2번째 인자: %rsi 레지스터
3번째 인자: %rdx 레지스터
4번째 인자: %rcx 레지스터
5번째 인자: %r8 레지스터
6번째 인자: %r9 레지스터
7번째 이후 인자: 스택 메모리에 저장
함수 반환값: %rax 레지스터
과거 8비트, 16비트, 32비트 프로그램과의 호환성을 위해 x86-64 CPU는 하나의 64비트 레지스터를 크기별로 나누어 부를 수 있습니다:
%rax: 64비트 (8바이트 전체)%eax: 하위 32비트 (4바이트)%ax: 하위 16비트 (2바이트)%al: 하위 8비트 (1바이트)규칙: 32비트 레지스터인 %eax에 값을 쓰면, 상위 32비트 영역은 CPU에 의해 자동으로 0으로 채워집니다.