2025-1 컴퓨터구조 (Assembly Language and machine code 1)

JayainHUFS·2025년 4월 23일
post-thumbnail

  • 아래의 포스팅은 한국외국어대학교 컴퓨터공학부 Mohsen Ali Alawami 교수님의 [컴퓨터구조] 강의를 기반으로 작성했습니다.
  • 또한, 상업적 의도는 전무하며, 단순 학습 용도의 교재 자료를 첨부함을 알립니다.

Intro

왜 어셈블리 언어를 배우는가?

어셈블리 언어는 하드웨어와 직접 상호작용하는 저수준 언어
컴퓨터 작동 원리와 하드웨어 수준의 이해를 깊게 도와줌
기계어(Machine Code)에 가깝기 때문에 CPU 동작을 명확히 파악 가능
메모리 관리 및 레지스터 구조를 이해하는 데 큰 도움이 됨

어셈블리 언어의 수준 (Level)

고급 언어 (High-level) -> 사람이 읽기 쉬움 (Python, Java 등)
중간 수준 언어 (C/C++) -> 성능과 이해도 균형
어셈블리 언어 -> 사람이 읽을 수 있는 수준에서 기계어와 가장 가까움
기계어 (Machine Language) -> 0과 1의 이진수, 사람이 읽기 어려움

어셈블리 개요 (Assembly Overview)

어셈블리어는 사람이 읽을 수 있는 기계어의 표현
컴파일러: 고급 언어 → 어셈블리어 (중간 코드)
어셈블러: 어셈블리어 → 기계어(0과 1로 구성된 바이너리 코드)
컴파일 과정을 통해 컴퓨터가 이해할 수 있는 명령으로 변환

Compiler vs. Interpreter

항목CompilerInterpreter
실행 방식전체 코드를 한 번에 번역한 줄씩 실시간 번역
속도빠름 (컴파일 후 실행)느림 (실시간 번역)
에러 처리모든 에러를 한 번에 탐지첫 번째 에러에서 즉시 중단
결과물독립 실행 파일 생성별도 실행 파일 없음
예시 언어C, C++, Java 등Python, JavaScript, Ruby 등
적합한 용도고성능 소프트웨어 (게임, 시스템 등)웹 개발, 스크립트 기반 애플리케이션

Assembly Language 활용 분야 요약

임베디드 시스템 (Embedded Systems)
-> 마이크로컨트롤러, IoT 장치, 실시간 시스템 등 저전력/저용량 환경에서 사용됨.

게임 개발 (Game Development)
-> 콘솔용 렌더링 엔진 최적화 등, 성능이 중요한 그래픽 처리에 사용.

운영체제 & 컴파일러 개발 (Operating Systems & Compilers)
-> 커널, 디바이스 드라이버 등 하드웨어와 밀접한 저수준 코드 구현에 사용.

성능 최적화 (Performance Optimization)
-> CPU 기반 애플리케이션의 실행 속도를 높이기 위해 사용.


Demo : Looking at an executable

C program instructions

int sum_array(int arr[], int nelems) {
    int sum = 0;
    for (int i = 0; i < nelems; i++) {
        sum += arr[i];
    }
    return sum;
}

Assembly program instructions

sum_array:
    mov     $0x0, %eax         # sum = 0
    mov     $0x0, %edx         # i = 0
.L1:
    cmp     %esi, %eax         # if i >= nelems, jump
    jge     .L2
    movslq  %eax, %rcx         # sign-extend i to rcx
    add     (%rdi,%rcx,4), %edx  # sum += arr[i]
    add     $0x1, %eax         # i++
    jmp     .L1
.L2:
    mov     %edx, %eax         # return sum
    ret

C code를 GCC Compiler를 이용해서 Assembly code로 만들기...


(1) 함수 시작 라벨과 메모리 주소

0000000000401136 <sum_array>:

분석
sum_array:
-> C 코드에서의 함수 이름과 동일함. 어셈블리에서는 이 라벨(label)을 통해 해당 함수의 시작 위치를 명시.

0x401136:
-> 이 라벨(sum_array)이 어디에 저장되어 있는지를 나타내는 실제 메모리 주소.

-> 함수가 호출되면, CPU는 이 주소로 점프해서 실행을 시작함.


(2) 어셈블리 명령어의 메모리 주소

401136:    b8 00 00 00 00       mov    $0x0,%eax
40113b:    ba 00 00 00 00       mov    $0x0,%edx
401140:    39 f0                cmp    %esi,%eax
...

분석
401136, 40113b, 401140 등의 앞부분은 각 명령어가 저장되어 있는 실제 메모리 주소임.

이 주소는 명령어마다 다르고, 코드가 순차적으로 메모리에 적재되어 있는 형태임.

즉, C 코드의 sum = 0;에 해당하는 어셈블리 명령어는 mov $0x0, %eax이고, 이게 401136 주소에 저장됨.


(3) 어셈블리 명령어 분석 - “Human-readable” 형태의 머신 코드

mov     $0x0, %eax         ; sum = 0
mov     $0x0, %edx         ; i = 0
cmp     %esi, %eax         ; i < nelems?
jge     40114f             ; if not, jump to end
movslq  %eax, %rcx         ; i → rcx (sign extend)
add     (%rdi,%rcx,4), %edx ; sum += arr[i]
add     $0x1, %eax         ; i++
jmp     401140             ; jump back to loop
mov     %edx, %eax         ; return sum
retq                       ; return

핵심 개념 정리

명령어설명
mov데이터를 이동시킴 (예: 레지스터 ← 값, 메모리 ← 레지스터 등)
cmp두 값을 비교하여 플래그 설정 (실제 계산은 하지 않음)
jge"Jump if Greater or Equal" - 비교 결과가 크거나 같으면 점프
movslq32비트를 64비트로 부호 확장하여 복사 (sign-extend)
add두 값을 더함 (레지스터나 메모리 포함 가능)
jmp무조건 점프 (조건 없이 특정 주소로 이동)
retq함수에서 복귀 (리턴 시 사용되는 명령어)

포인트
이 어셈블리 코드는 컴파일된 sum_array 함수의 루프 구조와 조건문, 반복문을 그대로 번역한 형태

인간이 이해할 수 있는 버전이지만, 결국은 머신 코드(바이트 코드)의 직전 단계


(4) 머신 코드 - 컴퓨터가 직접 해석하는 명령어

401136: b8 00 00 00 00
40113b: ba 00 00 00 00
401140: 39 f0
401142: 7d 0b
401144: 48 63 c8
401147: 03 14 8f
40114a: 83 c0 01
40114d: eb f1
40114f: 89 d0
401151: c3

핵심 개념 정리

구성 요소설명
메모리 주소각 명령어가 메모리에 저장된 위치. 프로그램은 이 순서대로 실행됨
머신 코드16진수(hexadecimal)로 표현된 명령어. 컴퓨터가 해석하는 가장 저수준 코드
명령어 크기명령어마다 바이트 수가 다름 (예: b8은 5바이트, 39 f0은 2바이트 등)
목적CPU는 이 값을 직접 읽고 명령 수행. 사람이 이해하기 어려움

포인트
사람이 이해하는 mov, add 등은 모두 이와 같은 바이트 코드로 변환됨

어셈블리 코드는 “읽기 쉬운 번역문”, 머신 코드는 “실제 실행파일”의 핵심


(5) 어셈블리 명령어의 구성 - Opcode란?

40114a:    83 c0 01        ; add    $0x1, %eax

설명
각 어셈블리 명령어는 명령 이름(opcode) 과 피연산자(operand) 로 구성됨

위 예시에서 add 가 opcode이며, 수행할 연산을 의미함

$0x1 과 %eax 는 이 명령이 동작할 대상인 피연산자임

핵심 개념 정리

구성 요소설명
Opcode (명령 코드)명령어의 동작을 정의함 (예: add, mov, cmp)
Operand (피연산자)명령이 작동할 대상 (예: 레지스터, 상수, 메모리 주소 등)

포인트
opcode 는 CPU가 수행할 연산 종류를 지정하며, 어셈블리어의 중심 키워드

사람이 읽기 쉬운 구조지만, 결국 머신 코드로 변환되어 실행됨


(6) 어셈블리 명령어의 구성 - Operand란?

40114a:    83 c0 01        ; add    $0x1, %eax

설명
각 어셈블리 명령어는 연산 대상(operand)을 가짐. 이들은 명령의 입력값 또는 결과 저장 위치가 됨.

위 예시에서 $0x1은 상수 값(소스), %eax는 레지스터(목적지)로 연산 대상임.

핵심 개념 정리

구성 요소설명
Source Operand연산에 사용될 값 (예: $0x1, 레지스터, 메모리 값 등)
Destination Operand연산 결과가 저장될 위치 (예: %eax, 메모리 주소 등)

포인트
피연산자는 연산의 흐름에서 값의 흐름(입력 → 출력)을 구성하며, 명령어의 의미를 완성시킴.

레지스터끼리의 연산, 상수와의 연산, 메모리 참조 연산 등 다양한 방식으로 나타남.


(7) Immediate 값 (즉시 값)의 의미

40114a:    83 c0 01        ; add    $0x1, %eax

설명
$로 시작하는 숫자는 “즉시 값 (Immediate)“을 의미함.

즉시 값은 상수값이며, 명령어 실행 시 메모리나 레지스터를 참조하지 않고 바로 사용됨.

위 예시에서는 add $0x1, %eax 는 eax 레지스터에 1을 더하라는 의미.

핵심 개념 정리

구성 요소설명
$숫자 (Immediate)즉시 값. 명령어에 포함되어 바로 사용되는 상수값 (예: $0x1)
용도연산 시 메모리나 레지스터 접근 없이 즉시 값을 사용하는 가장 빠른 방식

포인트
Immediate 값은 가장 빠른 연산 방법 중 하나로, 레지스터나 메모리 접근 없이 바로 값을 사용할 수 있음.


(8) 어셈블리 명령어의 구성 - Register란?

40114a:    83 c0 01        ; add    $0x1, %eax

설명
레지스터는 CPU 내부에 존재하는 매우 빠른 저장 공간이며, %eax와 같은 형태로 나타남

명령어에서 연산 대상이나 결과를 담기 위한 위치로 사용됨

핵심 개념 정리

구성 요소설명
%name (Register)CPU 내부의 저장 위치를 의미. 연산 대상이나 결과를 담는 데 사용됨 (예: %eax)
용도연산 속도를 높이기 위해 자주 사용하는 데이터를 저장함. 대부분의 연산은 레지스터 간에 이루어짐

포인트
레지스터는 메모리보다 빠르고 CPU가 직접 접근 가능함
효율적인 연산을 위해 대부분의 데이터는 연산 중 레지스터에 로드됨


Registers and The Assembly Level of Abstraction


Register란?

정의
Register는 CPU 내부에 존재하는 초고속 메모리로, 계산이나 명령 수행 중 임시 값을 저장하는 역할을 한다. 메인 메모리(RAM)보다 훨씬 빠르다.

포인트
CPU 안에 직접 존재 -> 접근 속도 매우 빠름
변수 저장, 연산 대상 저장 등에 사용
어셈블리어에서는 %rax, %eax 등으로 표기

핵심 개념 정리

구성 요소설명
RegisterCPU 안에 있는 매우 빠른 임시 저장 공간
위치메인 메모리가 아닌 CPU 내부
역할변수, 연산 대상, 함수 리턴값 등을 임시 저장
접근 방식이름으로 직접 접근 (예: %eax, %rcx)

32-bit -> 64-bit 전환

내용요약
2000년대 초반까지 컴퓨터는 32비트 시스템이 주류였고, 최대 4GB 메모리까지 접근 가능했다.

64비트로 전환되면서 최대 16 Exabytes(약 1.6×10¹⁹ Bytes)의 주소 공간이 확보되었다.

포인트
32-bit: 주소 2³² → 4GB
64-bit: 주소 2⁶⁴ → 16EB
현대 컴퓨터는 대부분 64-bit 기반

핵심 개념 정리

항목32-bit64-bit
주소 가능 메모리최대 4GB (2³²)최대 16EB (2⁶⁴)
주소 길이4바이트8바이트
레지스터 크기32비트64비트
사용 예시Windows XP 등Windows 10 이상, Mac, Linux 등

컴퓨터 아키텍처 관점에서의 Register

설명
Register는 CPU 내부에 존재
메모리는 주소 기반으로 접근하지만, Register는 이름으로 직접 접근
ALU(산술 논리 장치)는 Register를 활용해 연산 수행

전체 흐름 요약
(1) Disk에서 프로그램이 메모리(Main memory)로 로딩됨
(2) 실행 시, 명령어와 데이터는 Register로 로딩되어 ALU가 연산
(3) 연산 결과는 다시 메모리 혹은 Register에 저장됨

핵심 개념 정리

구성 요소설명
ALU연산을 수행하는 CPU의 핵심 장치
Register File여러 개의 레지스터가 모인 공간
Main Memory프로그램이 로딩되고 저장되는 공간 (RAM)
접근 차이메모리 → 주소로, 레지스터 → 이름으로 접근

64-bit registers used in Assembly

구성 요소설명
크기각 레지스터는 64비트 크기
개수총 16개의 고유한 이름을 가진 레지스터 사용 가능
주요 역할데이터 이동, 산술 연산 수행
함수 관련 기능파라미터 전달, 리턴 값 저장
속도매우 빠른 메모리 (CPU 내부에 위치)

All X-bit registers used in Assembly


Data Sizes 와 접미사

용어크기 (Byte)설명어셈블리 접미사
Byte11 바이트b
Word22 바이트w
Double Word44 바이트l
Quad Word88 바이트 (64비트)q

Register Sizes


Register Responsibilities


주요 레지스터와 역할

레지스터역할
%rax함수의 반환값을 저장 (return value) - first
%rip다음 실행할 명령어의 주소 저장 (instruction pointer, 64-bit에서는 %rip, 32-bit에서는 PC)
%rsp현재 스택의 최상단 주소 저장 (stack pointer, LIFO 구조)
%rdi, %rsi, %rdx, %rcx, %r8, %r9함수에 전달되는 인자(argument)들을 저장
%r10, %r11Callee (호출된 함수) 소유 레지스터
%rbx, %rbp, %r12 ~ %r15Caller (호출한 함수) 소유 레지스터

Caller vs Callee

  • Caller: 다른 함수를 호출하는 함수 (예: main)
  • Callee: 호출되어 실행되는 함수 (예: sum_array)

Register Responsibilities - %rip


(1) %rip 레지스터의 역할 - 시작 주소

설명
이 슬라이드는 %rip이 어떤 어셈블리 명령어에서 시작하는지를 보여줌.

0x4004ed 주소에 있는 55는 push %rbp라는 어셈블리 명령어의 머신 코드.

즉, %rip은 현재 실행 중인 명령어의 주소(0x4004ed)를 가리킴.

오른쪽 메모리 뷰는 명령어들이 메모리에 실제로 저장된 순서를 바이트 단위로 나타냄.

%rip은 항상 다음 실행할 명령어의 위치를 가리키며, CPU는 이 위치에서 명령을 읽어 실행함.


(2) %rip - Program Counter란?

설명
%rip 레지스터는 현재 CPU가 다음에 실행할 명령어의 메모리 주소를 저장하고 있음.

이 예시에서 %rip = 0x4004ed, 즉 첫 번째 명령어 push %rbp의 시작 주소를 가리킴.

오른쪽 메모리 테이블에 보면 0x4004ed 위치에 55가 저장되어 있으며, 이는 push %rbp의 머신 코드임.

%rip은 텍스트 영역(Text/code)에 저장된 명령어들을 순차적으로 가리키며, 프로그램 실행 흐름을 추적함.

요약하자면: %rip은 현재 실행 중인 명령어의 주소, 즉 프로그램의 흐름 제어용 핵심 레지스터.


(3) %rip - 다음 명령어로 이동

설명
첫 명령어 push %rbp(0x4004ed)가 실행된 후, %rip은 다음 명령어인 mov %rsp, %rbp의 주소인 0x4004ee로 이동함.

이는 바로 이어지는 명령어의 첫 바이트(48) 위치이며, 어셈블리 코드는 연속된 명령어들을 순차적으로 실행함.

오른쪽 메모리 테이블에서도 0x4004ee 위치에 48이 존재하고, 이어지는 89 e5는 mov %rsp, %rbp를 의미함.

이처럼 %rip은 한 명령어가 끝나면, 다음 명령어의 주소로 자동 갱신되며 프로그램 흐름을 추적함.

핵심: %rip은 프로그램 실행의 “지금 어디를 실행 중인지”를 알려주는 CPU 내부의 진행 포인터.


(4) %rip - 다음 명령어 movl 실행을 위한 이동

설명
%rip이 0x4004f1로 업데이트됨. 이는 다음 실행될 명령어 movl $0x0, -0x4(%rbp)의 시작 주소임.

movl은 상수 0x0을 스택 프레임의 오프셋 위치 -0x4(%rbp)에 저장하는 동작임.

오른쪽 메모리에서 0x4004f1 ~ 0x4004f8까지의 바이트들이 이 명령어를 구성하며, c7 45 fc 00 00 00 00으로 저장됨.

이 명령은 함수에서 지역 변수(예: sum = 0)를 초기화하는 역할을 함.

%rip이 이 주소를 가리킴으로써, 해당 명령어를 CPU가 인출(fetch)하고 실행(execute)하게 됨.

요약: %rip = 0x4004f1은 sum = 0 초기화 명령어의 시작 주소를 가리키며, 프로그램 흐름을 정확히 안내함.


(5) %rip - addl 명령어 실행 준비

설명
%rip이 0x4004f8을 가리키고 있으며, 이는 명령어 addl $0x1, -0x4(%rbp)의 시작 위치임.

이 명령은 movl로 초기화한 값(현재 스택에 저장된 sum)에 1을 더하는 연산을 수행.

명령어는 83 45 fc 01의 4바이트로 메모리에 저장되어 있으며, 0x4004f8부터 차례로 위치함.

%rip은 지금 이 addl 명령어를 CPU가 인출(fetch)해 실행하려는 시점을 나타냄.

요약: %rip = 0x4004f8은 sum += 1 동작을 수행하는 addl 명령어 위치를 가리킴. 연속적인 명령어 흐름을 통해 루프나 조건문 등의 구조를 구성함.


(6) %rip - jmp 명령어 실행 위치

설명
%rip이 현재 0x4004fc을 가리키고 있음. 해당 주소에는 jmp 0x4004f8 명령어가 존재함.

이 명령은 무조건 점프(jump)하는 명령어로, 반복(loop) 구조를 만드는 데 자주 사용됨.

즉, 이 명령이 실행되면 %rip은 다시 0x4004f8으로 이동하여 addl 명령을 반복 실행하게 됨.

명령어 jmp의 바이트 코드인 eb fa는 메모리 주소 0x4004fc와 0x4004fd에 저장되어 있음.

요약: %rip = 0x4004fc는 무조건 점프 명령을 가리킴. 이를 통해 루프를 구성하고 다음 명령의 위치를 강제로 제어함. 루프 제어의 핵심 명령 중 하나.


(7) %rip - jmp 명령 실행 결과

설명
jmp 명령은 무조건 점프(unconditional jump) 를 수행하는 명령어임.

현재 %rip = 0x4004fc에 위치한 jmp 0x4004f8 명령이 실행되면,

%rip 값은 즉시 0x4004f8로 바뀌고, 해당 위치에 있는 addl 명령어가 다음에 실행됨.

이처럼 jmp는 조건 없이 흐름을 원하는 위치로 이동시킴 → 루프(loop) 또는 함수 흐름 제어에 자주 사용됨.

요약: jmp는 조건 검사 없이 직접 명시된 주소로 %rip을 설정함. 따라서 이 명령은 프로그램 실행 흐름을 강제 변경하는 강력한 제어 도구.


(8) %rip - 무한 루프 (Infinite Loop)

설명
%rip 값이 다시 0x4004f8으로 설정되었음 → 이 주소에 위치한 addl 명령어로 점프(jmp) 됨.

이후 바로 아래의 jmp 명령으로 인해 또다시 %rip가 0x4004f8로 이동함.

이 동작이 반복되면서 무한 반복(loop) 구조가 형성됨.

C 코드로 보면 다음과 동일:

while (true) {
    sum += ...;
}

요약: 이 슬라이드는 %rip이 루프의 시작 주소로 되돌아가는 구조를 보여주며, 어셈블리 코드에서 조건 없는 점프(jmp)가 무한 루프를 구현하는 방식임을 설명함.


(9) %rip - 무한 루프 반복 지점

설명
현재 %rip의 값은 0x4004fc로, jmp 명령이 위치한 주소임.

이 명령은 조건 없이(unconditional) 0x4004f8으로 점프하여 루프의 시작 지점으로 이동시킴.

그 결과, 프로그램은 addl 명령 → jmp 명령 → 다시 addl 순으로 계속 반복하게 됨.

이 구조는 고전적인 무한 루프 구조로, 종료 조건 없이 지속적으로 명령을 실행함.

요약: %rip는 현재 실행할 명령의 주소를 나타내며, jmp 명령으로 다시 루프의 시작으로 이동해 무한 루프를 형성함. 이는 C 코드에서 while (true)와 동일한 구조임.


The "move" Instruction and Addressing Modes


mov

(1) mov 명령어 개요

설명
mov는 데이터를 한 위치에서 다른 위치로 복사하는 명령어.
형식: mov src, dst → src 값을 dst로 복사함.

src와 dst는 다음 중 하나일 수 있음:
Immediate (즉시 값): 예) $0x104 → 값 자체, 오직 src로만 사용 가능
Register (레지스터): 예) %rax, %rbx

Memory Location (메모리 주소): 예) 0x6005c0
※ src, dst 중 단 하나만 메모리 주소 가능

(2) mov 유효한/유효하지 않은 예시

잘못된 예시

mov 0x401, 0x201   ; "메모리 <-> 메모리 직접 이동은 불가"

올바른 예시

mov 0x401, %rax    ; 메모리 → 레지스터
mov %rax, 0x401    ; 레지스터 → 메모리

mov 명령은 레지스터를 반드시 중간 경유지로 사용해야 함.
메모리 <-> 메모리 직접 복사는 허용되지 않음.


Addressing modes in Assembly

(1) Addressing Modes - Immediate

설명

Immediate 모드는 상수값(즉시 값)을 바로 명령어에 포함시켜 사용하는 방식

표기법 : $숫자 → 예: $0x5 (5라는 값을 의미함)

형식 : mov $0x5, dst
-> 5라는 값을 dst(레지스터 또는 메모리)에 복사

올바른 예시

mov $0x5, %rax     ; 상수 -> 레지스터
mov $0x5, 0x102    ; 상수 -> 메모리 주소

잘못된 예시

mov %rbx, $0x5   ; 잘못된 형식 (destination에 상수 불가)

(2) Addressing Modes - Registers

설명

Register 모드는 레지스터끼리 데이터 이동 또는 레지스터 ↔ 메모리 간 이동을 수행함

표기법 : %레지스터명 (예: %rax, %rcx, %rbx)

형식 예시 :
mov %rbx, dst -> %rbx 값을 dst로 복사
mov src, %rcx -> src 값을 %rcx로 복사

올바른 예시

mov %rax, %rcx     ; 레지스터 → 레지스터
mov 0x102, %rcx    ; 메모리 → 레지스터
mov %rcx, 0x102    ; 레지스터 → 메모리

제약 조건
Register addressing은 빠르고 직접적인 접근 가능

src와 dst 중 하나는 반드시 레지스터여야 함

메모리 ↔ 메모리 직접 이동은 불가능

핵심 포인트
Register 모드는 CPU 내부 연산에서 가장 빠른 방법

레지스터를 이용한 데이터 이동은 다른 방식보다 빠르고 효율적임

메모리를 거치지 않기 때문에 복잡한 주소 계산이 없음.


(3) Addressing Modes - Direct Access (Absolute Address)

설명

Direct Access 모드는 절대 메모리 주소를 직접 지정하여 데이터를 읽거나 씀

연산자는 메모리 주소 자체를 포함하며, 주로 mov 명령어와 함께 사용됨

형식 예시:
mov 0x104, %rbx → 메모리 주소 0x104의 값을 %rbx로 복사 (읽기)
mov %rbx, 0x104 → %rbx의 값을 메모리 주소 0x104에 저장 (쓰기)

주요 특징
src 또는 dst 중 하나만 메모리 주소여야 함

즉시 값($)과는 달리, 메모리 주소는 0x 접두사만 사용

메모리에 직접 접근하므로 속도는 레지스터 접근보다 느림

용도
전역 변수나 특정 주소 공간에 접근할 때 사용

하드웨어 레지스터, 입출력 장치 제어 등에서 지정된 주소에 직접 접근 필요할 때 사용

정리

명령어 형식의미
mov 0x104, %rbx메모리 → 레지스터 (읽기)
mov %rbx, 0x104레지스터 → 메모리 (쓰기)

(4) Operand Forms: Indirect Access (간접 주소지정 방식)

mov    (%rbx), dst     ; %rbx가 가리키는 주소에 있는 값을 읽어서 dst로 복사
mov    src, (%rcx)     ; src의 값을 %rcx가 가리키는 메모리 주소에 저장

설명

이 방식은 메모리를 직접 지정하지 않고, 레지스터를 통해 “간접적으로” 접근

괄호 () 안의 레지스터는 “해당 레지스터가 가리키는 메모리 주소”를 의미함

즉, 간접적으로 메모리를 접근하는 방식이며 주소는 레지스터에 저장되어 있음

핵심 개념 정리

구성 요소설명
(%레지스터)해당 레지스터가 가리키는 메모리 주소의 값을 의미 (간접 접근 방식)
사용 목적주소를 직접 지정하지 않고 레지스터를 통해 간접적으로 메모리 접근
예시mov (%rbx), %rax : %rbx가 가리키는 주소의 값을 %rax로 복사
mov %rax, (%rcx) : %rax의 값을 %rcx가 가리키는 메모리 주소에 저장

포인트
실제 주소가 아닌 주소를 담은 레지스터를 통해 메모리 접근

레지스터는 이름으로 접근하지만, 그 내부 값은 주소

매우 유용한 방식으로 포인터 연산의 기반이 됨


Addressing Modes - Base + Displacement

mov 0x10(%rax), %rdx  ; %rax + 0x10 주소의 값을 %rdx로 복사
mov %rdx, 0x10(%rbx)  ; %rdx 값을 %rbx + 0x10 주소에 저장

설명

레지스터에 저장된 주소(=Base)와 상수값(=Displacement)을 더해 계산된 최종 주소의 메모리 값에 접근

핵심 개념 정리

구성 요소설명
0x10(%레지스터)레지스터에 저장된 주소에 0x10만큼 떨어진 메모리 주소로 접근
Displacement (0x10)기준 주소(Base)에 더해지는 오프셋 값
Base (%레지스터)기준이 되는 주소 값이 저장된 레지스터
예시 동작mov 0x10(%rax), %rdx → %rax + 0x10 주소의 값을 %rdx로 복사

포인트
간접 주소 접근 방식의 확장 형태

포인터 연산 또는 배열 요소 접근 시 자주 사용됨

매우 일반적인 주소 지정 패턴


(6) Operand Forms: Indexed & Indexed + Displacement

mov    (%rax,%rdx), dst          ; %rax + %rdx → 주소
mov    src, (%rax,%rdx)          ; → 주소에 저장

mov    0x10(%rax,%rdx), dst      ; %rax + %rdx + 0x10 → 주소
mov    src, 0x10(%rax,%rdx)      ; → 주소에 저장

설명

레지스터 두 개의 값을 더해서 메모리 주소로 접근하는 방식. 배열 인덱싱이나 오프셋 접근 등에 사용됨.

필요 시 displacement(상수)까지 함께 더해서 최종 주소 계산 가능.

핵심 개념 정리

구성 요소설명
(%rax,%rdx)%rax와 %rdx의 값을 더한 주소를 참조 (레지스터 + 레지스터)
0x10(%rax,%rdx)%rax + %rdx + 0x10: displacement까지 포함된 주소 참조
사용 목적배열에서 특정 오프셋 요소를 참조하거나, 이중 포인터와 유사한 연산
제약 조건인덱스는 레지스터만 가능하며, displacement는 상수만 허용

포인트
컴파일러가 배열 인덱스나 구조체 멤버 접근 시 자주 사용

(%reg1, %reg2) 형식은 간접 주소 연산이면서 동적 오프셋 처리에 유용

0x10(%reg1, %reg2)는 정적 오프셋(displacement)을 추가로 반영한 주소 계산 방식


눈물 날 것 같아....

profile
"REAL" 밑바닥부터 시작하는 데이터분석

0개의 댓글