
지금 우리는 컴퓨터 시스템 책의 3장을 딥다이브 중인데요.
3장의 목표는
C가 컴파일러와 어셈블러를 통해 "어셈블리 및 기계어 코드"로 변환되는 과정을 이해하기
입니다. 왜 어셈블리 및 기계어 코드를 이해하는 것이 중요한 이유는 다음과 같습니다.
성능 분석 및 최적화 시 중요한 힌트를 얻을 수 있고,
디버깅, 보안 취약점 분석 (예: 버퍼 오버플로우)에도 필수적이다.
그 변환과정 중에 어셈블리어가 있는데
기계어에 비해 어셈블리는 조금 더 인간 친화적으로 작성되어 있으므로 그래도 소스코드를 분석하고 읽을 수 있어요.
이번에는 어셈블리어를 읽는 방법을 공부하는 과정에서 "오퍼랜드" 가 뭔지 설명하려 해요.
우선 핵심부터 말할게요 오퍼랜드는
연산을 수행할 소스 값과, 그 결과를 저장할 목적지의 위치
컴퓨터는 캐싱을 위해 메모리를 자주 이동시키면서 저장하는데요.
자세한건 제가 적어둔 거있으니까 한 번 읽어보세요.
오퍼랜드는 "메모리의 위치" 혹은 "소스 값" 이예요.
간단하게 코드 예시를 볼게요.
대부분의 인스트럭션 ( 컴퓨터가 실행할 수 있는 기본 명령 단위 )은 하나 이상의 오퍼랜드를 가지는데
빨간 밑줄을 쳐놓은 부분이 인스트럭션이고
파란 동그라미가 오퍼랜드 입니다.
어떤 명령어를 실행할 때,
어떤 주소에 넣어야 할지,
어떤 값을 계산해야 할지 명시해줘야 하잖아요?
그게 오퍼랜드예요!
오퍼랜드는 총 3가지의 타입이 있는데요.
이렇게 3개가 있어요. 각각 어떻게 표현하는지 살펴볼게요.
Address Value
0x100 0xFF
0x104 0xAB
0x108 0x13
0x10C 0x11
%rax = 0x100
%rcx = 0x1
%rdx = 0x3
$0x100 = ?
상수 타입은 앞에 $를 붙여서 사용합니다.
$0x100 의 값은 뭘까요?
0xFF 일까요?
$0x100은 그냥 0x100 입니다.
주소도 아닙니다.
그냥 0x100 이라는 값이예요.
그래서 "즉시값"이라고도 부릅니다. 즉시 사용하는 값이요.
Address Value
0x100 0xFF
0x104 0xAB
0x108 0x13
0x10C 0x11
%rax = 0x100
%rcx = 0x1
%rdx = 0x3
%rcx = ?
%rax 는 특정 메모리 주소 (Address) 가 아닌 마치 변수처럼 직접 레지스터의 이름을 적어두었는데요.

x86-64 에서는 정해진 16개의 범용 레지스터가 있기 때문에 해당 이름을 변수로 생각해주시면 감사하겠습니다.
이렇게 오퍼랜드가 레지스터의 값을 가리키고 있는걸 "레지스터 타입" 이라고 합니다.
레지스터 타입을 작성했을 경우는
레지스터 가 가지고 있는 값이 그냥 나와요
%rcx = 0x100 이 나오게 됩니다.
Address Value
0x100 0xFF
0x104 0xAB
0x108 0x13
0x10C 0x11
%rax = 0x100
%rcx = 0x1
%rdx = 0x3
0x100 = ?
(%rax) = ?
메모리 주소 타입은 해당 메모리에서 값을 가져오는 걸 얘기해요.
0x100 은 주소 값 이고 앞에 상수타입 $ 가 붙지 않았으니까 해당 주소에 있는 값을 가져오라는 것으로 해석됩니다.
그래서 0x100 = 0xFF
(%rax) 는 레지스터타입을 괄호로 감싸주었네요. 이것도 마찬가지로 "레지스터가 갖고 있는 값의 주소로 가서 값을 가져와라"는 뜻입니다.
Address Value
0x100 0xFF
0x104 0xAB
0x108 0x13
0x10C 0x11
%rax = 0x100
%rcx = 0x1
%rdx = 0x3
4(%rax) = 0xAB
9(%rax,%rdx) = 0x11
(%rax,%rdx,4) = 0x11
이건 좀 헷갈려 미리 답을 달아두었어요.
만약 () 앞에 숫자가 붙어있다면 괄호안에 있는 값에 해당 숫자를 더해주면 돼요.
(%rax,%rdx) 처럼 여러개가 있는 경우라면 두 개를 더 해주면 돼요!
(%rax,%rdx,4) 처럼 마지막에 상수가있는 경우는 곱셈을 해주면 됩니다!
짜잔
예시를 들어서 보니까 훨씬 쉬워졌어요.
정리
에버랜드 보내줘요...ㅜㅜ