Assembly 제어 구조 및 프로그래밍

⭐⭐⭐ (핵심 섹션)
⭐⭐ (실용적인 내용)
⭐ (기초 이론)

1. 제어 구조 ⭐⭐⭐

1.1 플래그 레지스터와 조건부 실행

RFLAGS 레지스터 심화

RFLAGS (64비트)
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│0│0│0│0│O│D│I│T│S│Z│0│A│0│P│1│C│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
             F E D C B A 9 8 7 6 5 4 3 2 1 0

핵심 플래그들:
• CF (Carry Flag, bit 0): 부호 없는 산술에서 오버플로우
• PF (Parity Flag, bit 2): 결과의 하위 8비트에서 1의 개수가 짝수
• AF (Auxiliary Flag, bit 4): BCD 연산에서 보조 캐리
• ZF (Zero Flag, bit 6): 결과가 0
• SF (Sign Flag, bit 7): 결과의 최상위 비트 (음수 여부)
• OF (Overflow Flag, bit 11): 부호 있는 산술에서 오버플로우

플래그 설정 패턴

; 다양한 연산이 플래그에 미치는 영향
mov rax, 0
add rax, 0          ; ZF=1, SF=0, CF=0, OF=0

mov rax, 0x7FFFFFFFFFFFFFFF
add rax, 1          ; ZF=0, SF=1, CF=0, OF=1 (부호있는 오버플로우)

mov rax, 0xFFFFFFFFFFFFFFFF  
add rax, 1          ; ZF=1, SF=0, CF=1, OF=0 (부호없는 오버플로우)

; TEST 명령어 - 논리 AND 후 결과 버림
test rax, rax       ; RAX가 0인지 확인 (ZF 설정)
test rax, 1         ; RAX의 최하위 비트 확인
test rax, 0x80000000 ; 특정 비트가 설정되었는지 확인

1.2 비교 명령어 상세

CMP 명령어의 내부 동작

; CMP dst, src는 내부적으로 SUB dst, src와 동일하지만 결과를 저장하지 않음

cmp rax, rbx        ; 내부적으로 rax - rbx 계산
; 결과에 따른 플래그 설정:
; rax > rbx (부호없는): CF=0, ZF=0
; rax = rbx: ZF=1
; rax < rbx (부호없는): CF=1
; rax > rbx (부호있는): SF=OF, ZF=0  
; rax < rbx (부호있는): SF≠OF

; 실제 예제
cmp rax, 100
; RAX = 150인 경우: CF=0, ZF=0, SF=0, OF=0 (150 > 100)
; RAX = 100인 경우: CF=0, ZF=1, SF=0, OF=0 (150 = 100)  
; RAX = 50인 경우:  CF=1, ZF=0, SF=1, OF=0 (50 < 100)

부호 있는 vs 부호 없는 비교

; 같은 값이라도 해석에 따라 결과가 다름
mov rax, 0xFFFFFFFFFFFFFFFF  ; -1 (부호있는) 또는 큰 양수 (부호없는)
cmp rax, 0

; 부호 없는 비교로 해석하면
ja greater_unsigned     ; 점프함 (큰 양수 > 0)
jb less_unsigned       ; 점프 안함

; 부호 있는 비교로 해석하면  
jg greater_signed      ; 점프 안함 (-1 < 0)
jl less_signed         ; 점프함

1.3 분기 명령어 체계

조건부 점프 명령어 전체 목록

; 부호 없는 비교 기준
ja   / jnbe    ; Jump if Above (CF=0 and ZF=0)
jae  / jnb     ; Jump if Above or Equal (CF=0)  
jb   / jnae    ; Jump if Below (CF=1)
jbe  / jna     ; Jump if Below or Equal (CF=1 or ZF=1)

; 부호 있는 비교 기준
jg   / jnle    ; Jump if Greater (ZF=0 and SF=OF)
jge  / jnl     ; Jump if Greater or Equal (SF=OF)
jl   / jnge    ; Jump if Less (SF≠OF)
jle  / jng     ; Jump if Less or Equal (ZF=1 or SF≠OF)

; 등등 비교
je   / jz      ; Jump if Equal/Zero (ZF=1)
jne  / jnz     ; Jump if Not Equal/Not Zero (ZF=0)

; 개별 플래그 기준
jc             ; Jump if Carry (CF=1)
jnc            ; Jump if No Carry (CF=0)
jo             ; Jump if Overflow (OF=1) 
jno            ; Jump if No Overflow (OF=0)
js             ; Jump if Sign (SF=1)
jns            ; Jump if No Sign (SF=0)
jp  / jpe      ; Jump if Parity Even (PF=1)
jnp / jpo      ; Jump if Parity Odd (PF=0)

고급 분기 패턴

; 범위 체크 (0 ≤ value ≤ max)
bounds_check:
    cmp rax, 0
    jl out_of_bounds    ; 음수인 경우
    cmp rax, rdx        ; rdx = 최댓값
    ja out_of_bounds    ; 최댓값 초과인 경우
    ; 정상 범위 처리
    ret

out_of_bounds:
    ; 에러 처리
    ret

; 3방향 비교 (comparable pattern)
three_way_compare:
    cmp rax, rbx
    jl first_less       ; rax < rbx
    jg first_greater    ; rax > rbx
    ; rax == rbx인 경우
    mov rcx, 0
    ret

first_less:
    mov rcx, -1
    ret
    
first_greater:
    mov rcx, 1
    ret

1.4 반복문 구현 심화

고전적인 루프 패턴

; for (int i = 0; i < n; i++) 패턴
classic_for_loop:
    mov rcx, 0          ; i = 0
    
.loop_start:
    cmp rcx, r8         ; i < n (r8 = n)
    jge .loop_end       ; 조건 만족하지 않으면 종료
    
    ; 루프 바디
    ; ... 실제 작업들 ...
    
    inc rcx             ; i++
    jmp .loop_start
    
.loop_end:
    ret

; 최적화된 카운트다운 루프 (더 효율적)
optimized_countdown:
    mov rcx, r8         ; rcx = n
    
.loop_start:
    test rcx, rcx       ; rcx가 0인지 확인 (CMP보다 빠름)
    jz .loop_end        ; 0이면 종료
    
    ; 루프 바디
    ; ... 실제 작업들 ...
    
    dec rcx             ; count--
    jmp .loop_start     ; 조건 체크 없이 바로 점프
    
.loop_end:
    ret

고성능 루프 최적화 기법

; 루프 언롤링 (Loop Unrolling)
unrolled_copy_loop:
    ; 4개씩 처리하여 루프 오버헤드 감소
    mov rcx, r8         ; 전체 개수
    shr rcx, 2          ; 4로 나눔 (4개씩 처리)
    
.unrolled_loop:
    test rcx, rcx
    jz .handle_remainder
    
    ; 4개를 한 번에 처리
    mov rax, [rsi]
    mov [rdi], rax
    mov rax, [rsi + 8]
    mov [rdi + 8], rax
    mov rax, [rsi + 16]
    mov [rdi + 16], rax
    mov rax, [rsi + 24]
    mov [rdi + 24], rax
    
    add rsi, 32
    add rdi, 32
    dec rcx
    jmp .unrolled_loop
    
.handle_remainder:
    ; 나머지 처리 (0~3개)
    mov rcx, r8
    and rcx, 3          ; 나머지 계산
    rep movsb           ; 나머지 바이트들 복사
    ret

; 브랜치 예측 최적화를 고려한 루프
branch_optimized_loop:
    mov rcx, r8
    
.loop_start:
    ; 가장 가능성 높은 경우를 먼저 배치
    dec rcx
    jz .loop_end        ; 루프 종료 조건을 마지막에
    
    ; 루프 바디 (가장 자주 실행되는 부분)
    ; ...
    
    jmp .loop_start     ; 무조건 점프 (예측하기 쉬움)
    
.loop_end:
    ret

복잡한 반복 구조

; 중첩 루프 (이차원 배열 처리)
nested_loops:
    ; for (i = 0; i < rows; i++)
    ;   for (j = 0; j < cols; j++)
    ;     matrix[i][j] = i * cols + j
    
    mov r9, 0           ; i = 0
    
.outer_loop:
    cmp r9, r10         ; i < rows
    jge .outer_end
    
    mov r11, 0          ; j = 0
    
.inner_loop:
    cmp r11, r12        ; j < cols  
    jge .inner_end
    
    ; 인덱스 계산: i * cols + j
    mov rax, r9         ; i
    imul rax, r12       ; i * cols
    add rax, r11        ; i * cols + j
    
    ; 메모리 주소 계산 후 저장
    mov [rsi + rax * 8], rax
    
    inc r11             ; j++
    jmp .inner_loop
    
.inner_end:
    inc r9              ; i++
    jmp .outer_loop
    
.outer_end:
    ret

1.5 고급 제어 흐름 패턴

상태 머신 구현

; 간단한 문자열 파서 상태 머신
string_parser:
    ; 상태: 0=시작, 1=숫자읽기, 2=문자읽기, 3=종료
    mov r8, 0           ; 현재 상태
    mov r9, 0           ; 현재 인덱스
    
.parse_loop:
    mov al, [rsi + r9]  ; 현재 문자 읽기
    test al, al         ; 문자열 끝 확인
    jz .state_end
    
    ; 상태별 점프 테이블
    cmp r8, 3
    jae .state_end
    jmp [state_table + r8 * 8]
    
state_table:
    dq .state_start     ; 상태 0
    dq .state_number    ; 상태 1  
    dq .state_letter    ; 상태 2
    dq .state_end       ; 상태 3

.state_start:
    cmp al, '0'
    jl .check_letter
    cmp al, '9'
    jle .to_number_state
    
.check_letter:
    cmp al, 'A'
    jl .parse_error
    cmp al, 'Z'
    jle .to_letter_state
    jmp .parse_error
    
.to_number_state:
    mov r8, 1
    jmp .next_char
    
.to_letter_state:
    mov r8, 2
    jmp .next_char
    
.state_number:
    ; 숫자 상태에서의 처리
    cmp al, '0'
    jl .state_transition
    cmp al, '9'
    jle .next_char
    jmp .state_transition
    
.state_letter:
    ; 문자 상태에서의 처리  
    cmp al, 'A'
    jl .state_transition
    cmp al, 'Z'
    jle .next_char
    
.state_transition:
    ; 상태 전환 로직
    mov r8, 0           ; 시작 상태로 돌아감
    jmp .parse_loop
    
.next_char:
    inc r9
    jmp .parse_loop
    
.parse_error:
    mov rax, -1         ; 에러 코드
    ret
    
.state_end:
    mov rax, 0          ; 성공
    ret

점프 테이블을 이용한 스위치문

; switch-case 구문 최적화 구현
switch_optimized:
    ; RAX = switch value (0-7 범위 가정)
    cmp rax, 7
    ja .default_case
    
    ; 점프 테이블을 이용한 O(1) 분기
    jmp [jump_table + rax * 8]
    
jump_table:
    dq .case_0
    dq .case_1  
    dq .case_2
    dq .case_3
    dq .case_4
    dq .case_5
    dq .case_6
    dq .case_7

.case_0:
    ; case 0 처리
    mov rbx, 100
    jmp .switch_end
    
.case_1:
    ; case 1 처리
    mov rbx, 200
    jmp .switch_end
    
.case_2:
    ; case 2 처리
    mov rbx, 300
    jmp .switch_end
    
.case_3:
    ; case 3 처리 - fall through 예제
    mov rbx, 400
    ; 다음 케이스로 계속 (break 없음)
    
.case_4:
    ; case 4 처리 (case 3에서도 실행됨)
    add rbx, 50
    jmp .switch_end
    
.case_5:
.case_6:
.case_7:
    ; 여러 케이스를 하나로 처리
    mov rbx, 999
    jmp .switch_end
    
.default_case:
    ; default case
    mov rbx, -1
    
.switch_end:
    ret

2. 함수와 스택 관리 ⭐⭐⭐

2.1 스택의 동작 원리 심화

스택 프레임의 완전한 구조

높은 주소
┌─────────────────┐ ← RSP (함수 호출 전)
│   매개변수 n     │   
├─────────────────┤
│   매개변수 7     │ (7번째 이후 매개변수들)
├─────────────────┤ 
│   매개변수 6     │
├─────────────────┤
│   반환 주소      │ ← call 명령어가 저장
├─────────────────┤ ← RSP (함수 진입 직후)
│   이전 RBP      │ ← push rbp로 저장
├─────────────────┤ ← RBP (새로운 베이스)
│   지역변수 1     │
├─────────────────┤
│   지역변수 2     │
├─────────────────┤
│   ...           │
├─────────────────┤
│   임시 저장소    │
├─────────────────┤ ← RSP (함수 실행 중)
│   (여유 공간)    │
└─────────────────┘
낮은 주소

스택 오퍼레이션의 세부 사항

detailed_stack_operations:
    ; 함수 호출 전 스택 준비
    push rax        ; 인수 8 (오른쪽부터)
    push rbx        ; 인수 7
    push rcx        ; 인수 6
    ; 첫 6개 인수는 레지스터로: RDI, RSI, RDX, RCX, R8, R9
    mov rdi, arg1
    mov rsi, arg2
    mov rdx, arg3
    mov rcx, arg4
    mov r8, arg5
    mov r9, arg6
    
    call complex_function
    
    ; 스택 정리 (caller가 책임)
    add rsp, 24     ; 3개 * 8바이트 = 24바이트
    ret

complex_function:
    ; 프롤로그 (Prologue)
    push rbp        ; 이전 베이스 포인터 저장
    mov rbp, rsp    ; 새로운 베이스 포인터 설정
    sub rsp, 48     ; 지역변수용 공간 확보 (6개 * 8바이트)
    
    ; 호출자 저장 레지스터 보존 (필요한 경우만)
    push rbx
    push r12
    push r13
    
    ; 매개변수 접근
    mov rax, rdi    ; 첫 번째 매개변수
    mov rbx, rsi    ; 두 번째 매개변수
    mov rcx, [rbp + 16]  ; 7번째 매개변수 (스택에서)
    mov rdx, [rbp + 24]  ; 8번째 매개변수
    
    ; 지역변수 접근
    mov qword [rbp - 8], 100    ; 첫 번째 지역변수
    mov qword [rbp - 16], 200   ; 두 번째 지역변수
    
    ; 함수 로직...
    
    ; 에필로그 (Epilogue)
    pop r13         ; 보존된 레지스터 복원 (역순)
    pop r12
    pop rbx
    
    mov rsp, rbp    ; 스택 포인터 복원 (또는 add rsp, 48)
    pop rbp         ; 이전 베이스 포인터 복원
    ret             ; 반환 (RAX에 반환값)

2.2 호출 규약 (Calling Conventions) 상세

System V ABI (Linux/Unix)

; System V AMD64 ABI 완전 구현
sysv_function:
    ; 매개변수: RDI, RSI, RDX, RCX, R8, R9, 나머지는 스택
    ; 반환값: RAX, RDX (큰 값의 경우)
    ; 보존 레지스터: RBX, RSP, RBP, R12-R15
    ; 일시 레지스터: RAX, RCX, RDX, RSI, RDI, R8-R11
    
    push rbp
    mov rbp, rsp
    sub rsp, 32         ; 지역변수 공간
    
    ; 보존해야 할 레지스터 저장
    push rbx
    push r12
    
    ; 부동소수점 매개변수는 XMM0-XMM7 사용
    movsd xmm8, xmm0    ; 첫 번째 실수 매개변수 보존
    
    ; 함수 로직
    mov rax, rdi        ; 첫 번째 정수 매개변수
    add rax, rsi        ; 두 번째 정수 매개변수와 더함
    
    ; 정리
    pop r12
    pop rbx
    mov rsp, rbp
    pop rbp
    ret                 ; 반환값은 RAX에

Microsoft x64 Calling Convention (Windows)

; Microsoft x64 호출 규약
windows_function:
    ; 매개변수: RCX, RDX, R8, R9, 나머지는 스택
    ; 반환값: RAX
    ; 보존 레지스터: RBX, RBP, RDI, RSI, RSP, R12-R15, XMM6-XMM15
    ; Shadow space: 32바이트 (caller가 할당)
    
    push rbp
    mov rbp, rsp
    sub rsp, 64         ; 지역변수 + 정렬
    
    ; Shadow space는 이미 caller가 할당함
    ; 매개변수들을 shadow space에 저장 (디버깅용)
    mov [rbp + 16], rcx     ; 첫 번째 매개변수
    mov [rbp + 24], rdx     ; 두 번째 매개변수
    mov [rbp + 32], r8      ; 세 번째 매개변수
    mov [rbp + 40], r9      ; 네 번째 매개변수
    
    ; 보존 레지스터 저장
    push rdi
    push rsi
    
    ; 함수 로직
    mov rax, rcx
    add rax, rdx
    imul rax, r8
    
    ; 정리
    pop rsi
    pop rdi
    mov rsp, rbp
    pop rbp
    ret

2.3 고급 함수 패턴

재귀 함수 구현

; 팩토리얼 계산 (재귀)
factorial:
    ; 매개변수: RDI = n
    ; 반환값: RAX = n!
    
    push rbp
    mov rbp, rsp
    push rbx            ; n 값을 보존하기 위해
    
    mov rbx, rdi        ; n을 RBX에 저장
    
    ; 기저 조건: n <= 1이면 1 반환
    cmp rdi, 1
    jle .base_case
    
    ; 재귀 호출: factorial(n-1)
    dec rdi             ; n-1
    call factorial      ; factorial(n-1) 호출
    
    ; 결과: RAX = (n-1)!
    imul rax, rbx       ; RAX = n * (n-1)!
    jmp .end
    
.base_case:
    mov rax, 1
    
.end:
    pop rbx
    pop rbp
    ret

; 꼬리 재귀 최적화 버전
factorial_tail_recursive:
    ; 매개변수: RDI = n, RSI = accumulator
    ; 반환값: RAX = n!
    
    cmp rdi, 1
    jle .return_acc
    
    ; accumulator = accumulator * n
    imul rsi, rdi
    
    ; n = n - 1
    dec rdi
    
    ; 꼬리 호출 (스택 프레임 재사용)
    jmp factorial_tail_recursive
    
.return_acc:
    mov rax, rsi
    ret

가변 인수 함수

; printf 스타일 가변 인수 함수 (System V ABI)
my_printf:
    ; 첫 번째 매개변수(format string): RDI
    ; 가변 인수들: RSI, RDX, RCX, R8, R9, 그 다음은 스택
    
    push rbp
    mov rbp, rsp
    sub rsp, 176        ; va_list 구조체용 공간
    
    ; va_list 구조체 초기화
    mov dword [rbp - 176], 0        ; gp_offset (general purpose)
    mov dword [rbp - 172], 48       ; fp_offset (floating point)
    lea rax, [rbp + 16]             ; overflow_arg_area
    mov [rbp - 168], rax
    lea rax, [rbp - 160]            ; reg_save_area
    mov [rbp - 160], rax
    
    ; 레지스터에 있는 인수들을 저장 영역에 백업
    mov [rbp - 160], rsi    ; 두 번째 인수
    mov [rbp - 152], rdx    ; 세 번째 인수
    mov [rbp - 144], rcx    ; 네 번째 인수
    mov [rbp - 136], r8     ; 다섯 번째 인수
    mov [rbp - 128], r9     ; 여섯 번째 인수
    
    ; XMM 레지스터들도 저장
    movdqa [rbp - 96], xmm0
    movdqa [rbp - 80], xmm1
    movdqa [rbp - 64], xmm2
    movdqa [rbp - 48], xmm3
    movdqa [rbp - 32], xmm4
    movdqa [rbp - 16], xmm5
    
    ; 실제 printf 로직은 여기에...
    ; format string 파싱하고 va_list에서 인수 추출
    
    mov rsp, rbp
    pop rbp
    ret

함수 포인터와 콜백

; 함수 포인터 배열을 이용한 다형성
operation_table:
    dq add_func
    dq sub_func  
    dq mul_func
    dq div_func

calculator:
    ; 매개변수: RDI = operation (0-3), RSI = a, RDX = b
    ; 반환값: RAX = result
    
    push rbp
    mov rbp, rsp
    
    ; 범위 체크
    cmp rdi, 3
    ja .invalid_op
    
    ; 함수 포인터 테이블에서 호출
    push rsi            ; 매개변수 보존
    push rdx
    call [operation_table + rdi * 8]
    pop rdx             ; 정리 (필요시)
    pop rsi
    
    jmp .end
    
.invalid_op:
    mov rax, -1         ; 에러 코드
    
.end:
    pop rbp
    ret

add_func:
    mov rax, rsi
    add rax, rdx
    ret
    
sub_func:
    mov rax, rsi
    sub rax, rdx
    ret
    
mul_func:
    mov rax, rsi
    imul rax, rdx
    ret
    
div_func:
    mov rax, rsi
    cqo                 ; RDX:RAX로 확장
    idiv rdx
    ret

2.4 스택 프레임 최적화

프레임 포인터 생략 최적화

; 프레임 포인터 사용 (일반적)
with_frame_pointer:
    push rbp            ; 8바이트
    mov rbp, rsp        ; 추가 명령어
    sub rsp, 32         ; 지역변수 공간
    
    mov [rbp - 8], rdi  ; 지역변수 접근
    mov [rbp - 16], rsi
    
    add rsp, 32         ; 정리
    pop rbp             ; 8바이트 + 추가 명령어
    ret

; 프레임 포인터 생략 (최적화)
without_frame_pointer:
    sub rsp, 32         ; 지역변수 공간만 할당
    
    mov [rsp + 24], rdi ; 직접 RSP 기준으로 접근
    mov [rsp + 16], rsi
    
    add rsp, 32         ; 간단한 정리
    ret
    
; 주의: 프레임 포인터 생략 시 디버깅이 어려워질 수 있음
; 컴파일러 옵션: -fomit-frame-pointer

스택 할당 최적화

; 스택 탐지 회피 (Stack Probe Avoidance)
large_stack_allocation:
    ; 4KB 이상의 스택 할당 시 페이지 단위로 접근
    mov rax, 8192       ; 8KB 할당 예정
    
.probe_loop:
    sub rsp, 4096       ; 4KB씩 할당
    mov [rsp], byte 0   ; 페이지 접근 (스택 가드 페이지 탐지)
    sub rax, 4096
    test rax, rax
    jg .probe_loop
    
    ; 나머지 공간 할당
    test rax, rax
    jz .allocation_done
    add rsp, rax        ; 음수이므로 더하면 빼는 효과
    
.allocation_done:
    ; 큰 지역변수 사용...
    
    add rsp, 8192       ; 전체 공간 해제
    ret

3. 메모리와 데이터 구조 ⭐⭐⭐

3.1 배열 처리 심화

다차원 배열 접근

; 2차원 배열: matrix[rows][cols]
; 주소 계산: base + (row * cols + col) * element_size

matrix_access:
    ; 매개변수: RDI = base_addr, RSI = row, RDX = col, 
    ;          RCX = cols, R8 = element_size
    ; 반환값: RAX = element address
    
    mov rax, rsi        ; row
    imul rax, rcx       ; row * cols
    add rax, rdx        ; row * cols + col
    imul rax, r8        ; (row * cols + col) * element_size
    add rax, rdi        ; base + offset
    ret

; 3차원 배열: array[depth][rows][cols]
array_3d_access:
    ; 매개변수: RDI = base, RSI = d, RDX = r, RCX = c,
    ;          R8 = rows, R9 = cols, [rsp+8] = element_size
    
    push rbp
    mov rbp, rsp
    
    mov rax, rsi        ; d
    imul rax, r8        ; d * rows
    add rax, rdx        ; d * rows + r
    imul rax, r9        ; (d * rows + r) * cols
    add rax, rcx        ; (d * rows + r) * cols + c
    imul rax, [rbp + 16] ; * element_size
    add rax, rdi        ; + base
    
    pop rbp
    ret

; 고성능 행렬 곱셈 (캐시 최적화)
matrix_multiply_optimized:
    ; C = A * B (모두 NxN 행렬)
    ; 매개변수: RDI = A, RSI = B, RDX = C, RCX = N
    
    push rbp
    mov rbp, rsp
    push rbx
    push r12
    push r13
    push r14
    push r15
    
    mov r12, rdi        ; A
    mov r13, rsi        ; B  
    mov r14, rdx        ; C
    mov r15, rcx        ; N
    
    ; 블록 단위로 계산 (캐시 친화적)
    mov r8, 0           ; i = 0
    
.i_loop:
    cmp r8, r15
    jge .i_done
    
    mov r9, 0           ; j = 0
    
.j_loop:
    cmp r9, r15
    jge .j_done
    
    ; C[i][j] = 0으로 초기화
    mov rax, r8
    imul rax, r15
    add rax, r9
    mov qword [r14 + rax * 8], 0
    
    mov r10, 0          ; k = 0
    
.k_loop:
    cmp r10, r15
    jge .k_done
    
    ; A[i][k] 주소 계산
    mov rax, r8
    imul rax, r15
    add rax, r10
    mov rbx, [r12 + rax * 8]    ; A[i][k]
    
    ; B[k][j] 주소 계산  
    mov rax, r10
    imul rax, r15
    add rax, r9
    mov rcx, [r13 + rax * 8]    ; B[k][j]
    
    ; C[i][j] += A[i][k] * B[k][j]
    imul rbx, rcx
    mov rax, r8
    imul rax, r15
    add rax, r9
    add [r14 + rax * 8], rbx
    
    inc r10
    jmp .k_loop
    
.k_done:
    inc r9
    jmp .j_loop
    
.j_done:
    inc r8
    jmp .i_loop
    
.i_done:
    pop r15
    pop r14
    pop r13
    pop r12
    pop rbx
    pop rbp
    ret

3.2 포인터와 주소 연산

복잡한 포인터 조작

; 포인터의 포인터 (**ptr)
pointer_to_pointer:
    ; RDI = int** ptr
    mov rax, [rdi]      ; *ptr (int* 값)
    mov rax, [rax]      ; **ptr (int 값)
    ret

; 함수 포인터 배열
function_pointer_array:
    ; RDI = 함수 포인터 배열, RSI = 인덱스
    mov rax, [rdi + rsi * 8]    ; 함수 주소 로드
    call rax                     ; 간접 호출
    ret

; 구조체 내 포인터 멤버 접근
struct_pointer_access:
    ; 구조체: { int* data; size_t count; char* name; }
    ; RDI = struct pointer, RSI = array index
    
    mov rax, [rdi]              ; struct->data
    mov rbx, [rdi + 8]          ; struct->count
    
    ; 범위 체크
    cmp rsi, rbx
    jae .out_of_bounds
    
    mov rax, [rax + rsi * 4]    ; data[index] (int는 4바이트)
    ret
    
.out_of_bounds:
    mov rax, -1
    ret

동적 메모리 관리 패턴

; 간단한 메모리 풀 할당자
memory_pool:
    .pool_start     dq 0        ; 풀 시작 주소
    .pool_size      dq 0        ; 풀 크기
    .current_pos    dq 0        ; 현재 할당 위치
    .allocated      dq 0        ; 할당된 바이트 수

init_memory_pool:
    ; 매개변수: RDI = 풀 크기
    push rbp
    mov rbp, rsp
    
    ; mmap으로 메모리 할당
    mov rax, 9              ; sys_mmap
    mov rsi, rdi            ; 크기
    mov rdi, 0              ; 주소 (시스템이 결정)
    mov rdx, 3              ; PROT_READ | PROT_WRITE
    mov r10, 34             ; MAP_PRIVATE | MAP_ANONYMOUS
    mov r8, -1              ; fd
    mov r9, 0               ; offset
    syscall
    
    cmp rax, -1
    je .alloc_failed
    
    ; 풀 정보 저장
    mov [memory_pool.pool_start], rax
    mov [memory_pool.pool_size], rsi
    mov [memory_pool.current_pos], rax
    mov qword [memory_pool.allocated], 0
    
    mov rax, 0              ; 성공
    jmp .end
    
.alloc_failed:
    mov rax, -1             ; 실패
    
.end:
    pop rbp
    ret

pool_alloc:
    ; 매개변수: RDI = 할당할 크기
    ; 반환값: RAX = 할당된 주소 (실패시 0)
    
    ; 정렬 (8바이트 경계)
    add rdi, 7
    and rdi, -8
    
    ; 공간 충분한지 확인
    mov rax, [memory_pool.allocated]
    add rax, rdi
    cmp rax, [memory_pool.pool_size]
    ja .no_space
    
    ; 할당
    mov rax, [memory_pool.current_pos]
    add [memory_pool.current_pos], rdi
    add [memory_pool.allocated], rdi
    
    ret
    
.no_space:
    xor rax, rax            ; NULL 반환
    ret

3.3 문자열 처리 고급

고성능 문자열 함수

; 최적화된 strlen (SSE 사용)
strlen_optimized:
    ; 매개변수: RDI = 문자열 주소
    ; 반환값: RAX = 길이
    
    mov rsi, rdi            ; 원본 주소 보존
    
    ; 16바이트 정렬 확인
    mov rax, rdi
    and rax, 15
    jz .aligned
    
    ; 정렬되지 않은 부분 처리
.unaligned_loop:
    cmp byte [rdi], 0
    je .found_null
    inc rdi
    inc rax
    cmp rax, 16
    jne .unaligned_loop
    
.aligned:
    ; SSE를 이용한 16바이트씩 처리
    pxor xmm0, xmm0         ; NULL 바이트 패턴
    
.sse_loop:
    movdqa xmm1, [rdi]      ; 16바이트 로드
    pcmpeqb xmm1, xmm0      ; NULL 바이트 찾기
    pmovmskb eax, xmm1      ; 비트마스크 생성
    test eax, eax
    jnz .found_in_chunk
    
    add rdi, 16
    jmp .sse_loop
    
.found_in_chunk:
    ; 정확한 위치 찾기
    bsf eax, eax            ; 첫 번째 설정된 비트 찾기
    add rdi, rax
    
.found_null:
    sub rdi, rsi            ; 길이 계산
    mov rax, rdi
    ret

; 고성능 메모리 복사 (SIMD 최적화)
memcpy_optimized:
    ; 매개변수: RDI = dest, RSI = src, RDX = size
    ; 반환값: RAX = dest
    
    push rdi                ; 반환값용 dest 보존
    
    ; 작은 크기는 바이트 단위로 처리
    cmp rdx, 32
    jb .byte_copy
    
    ; 큰 크기는 SIMD로 처리
    mov rcx, rdx
    shr rcx, 5              ; 32바이트씩 처리할 횟수
    
.simd_loop:
    movdqu xmm0, [rsi]      ; 16바이트 로드
    movdqu xmm1, [rsi + 16] ; 다음 16바이트
    movdqu [rdi], xmm0      ; 16바이트 저장
    movdqu [rdi + 16], xmm1 ; 다음 16바이트 저장
    
    add rsi, 32
    add rdi, 32
    dec rcx
    jnz .simd_loop
    
    ; 나머지 바이트 처리
    and rdx, 31             ; 나머지 계산
    
.byte_copy:
    mov rcx, rdx
    rep movsb               ; 바이트 단위 복사
    
    pop rax                 ; dest 반환
    ret

3.4 구조체와 공용체

복잡한 구조체 조작

; 구조체 정의 (매크로로)
%define PERSON_NAME_OFFSET   0
%define PERSON_AGE_OFFSET    64
%define PERSON_SALARY_OFFSET 68
%define PERSON_NEXT_OFFSET   76
%define PERSON_SIZE          84

; 연결 리스트 노드 구조체
; struct Person {
;     char name[64];      // offset 0
;     int age;            // offset 64
;     float salary;       // offset 68
;     struct Person* next; // offset 76
; };

create_person:
    ; 매개변수: RDI = name, RSI = age, XMM0 = salary
    ; 반환값: RAX = Person* (할당된 구조체 주소)
    
    push rbp
    mov rbp, rsp
    push rdi
    push rsi
    sub rsp, 16
    movss [rbp - 20], xmm0  ; salary 보존
    
    ; 메모리 할당
    mov rdi, PERSON_SIZE
    call malloc             ; 시스템의 malloc 호출
    test rax, rax
    jz .alloc_failed
    
    mov r8, rax             ; 할당된 주소 보존
    
    ; name 복사
    mov rdi, rax            ; dest = struct
    mov rsi, [rbp - 8]      ; src = name parameter
    mov rdx, 63             ; 최대 63문자 + null
    call strncpy
    
    ; age 설정
    mov rdi, [rbp - 16]     ; age parameter
    mov [r8 + PERSON_AGE_OFFSET], edi
    
    ; salary 설정
    movss xmm0, [rbp - 20]
    movss [r8 + PERSON_SALARY_OFFSET], xmm0
    
    ; next 포인터 초기화
    mov qword [r8 + PERSON_NEXT_OFFSET], 0
    
    mov rax, r8             ; 구조체 주소 반환
    jmp .end
    
.alloc_failed:
    xor rax, rax            ; NULL 반환
    
.end:
    mov rsp, rbp
    pop rbp
    ret

; 연결 리스트에 노드 추가
list_append:
    ; 매개변수: RDI = head*, RSI = new_person
    ; 반환값: RAX = new head
    
    ; 리스트가 비어있는 경우
    cmp qword [rdi], 0
    je .empty_list
    
    ; 마지막 노드 찾기
    mov rax, [rdi]          ; current = head
    
.find_last:
    cmp qword [rax + PERSON_NEXT_OFFSET], 0
    je .found_last
    mov rax, [rax + PERSON_NEXT_OFFSET]
    jmp .find_last
    
.found_last:
    mov [rax + PERSON_NEXT_OFFSET], rsi
    mov rax, [rdi]          ; 기존 head 반환
    ret
    
.empty_list:
    mov [rdi], rsi          ; head = new_person
    mov rax, rsi            ; new head 반환
    ret

공용체 (Union) 활용

; 공용체: 같은 메모리 공간을 다른 타입으로 해석
; union Value {
;     int64_t as_int;
;     double as_double;
;     void* as_ptr;
;     char as_bytes[8];
; };

union_operations:
    ; 매개변수: RDI = union Value*, RSI = type (0=int, 1=double, 2=ptr)
    
    cmp rsi, 0
    je .handle_int
    cmp rsi, 1  
    je .handle_double
    cmp rsi, 2
    je .handle_ptr
    ret
    
.handle_int:
    mov rax, [rdi]          ; as_int로 읽기
    ; 정수 처리 로직
    ret
    
.handle_double:
    movsd xmm0, [rdi]       ; as_double로 읽기
    ; 실수 처리 로직
    ret
    
.handle_ptr:
    mov rax, [rdi]          ; as_ptr로 읽기
    ; 포인터 처리 로직
    ret

4. 시스템 프로그래밍 ⭐⭐

4.1 시스템 호출 심화

Linux 시스템 호출 완전 가이드

; 주요 시스템 호출 번호들
%define SYS_READ        0
%define SYS_WRITE       1
%define SYS_OPEN        2
%define SYS_CLOSE       3
%define SYS_STAT        4
%define SYS_FSTAT       5
%define SYS_LSTAT       6
%define SYS_POLL        7
%define SYS_LSEEK       8
%define SYS_MMAP        9
%define SYS_MPROTECT    10
%define SYS_MUNMAP      11
%define SYS_BRK         12
%define SYS_RT_SIGACTION 13
%define SYS_RT_SIGPROCMASK 14
%define SYS_RT_SIGRETURN 15
%define SYS_IOCTL       16
%define SYS_PREAD64     17
%define SYS_PWRITE64    18
%define SYS_READV       19
%define SYS_WRITEV      20
%define SYS_ACCESS      21
%define SYS_PIPE        22
%define SYS_SELECT      23
%define SYS_SCHED_YIELD 24
%define SYS_MREMAP      25
%define SYS_MSYNC       26
%define SYS_MINCORE     27
%define SYS_MADVISE     28
%define SYS_SHMGET      29
%define SYS_SHMAT       30
%define SYS_SHMCTL      31
%define SYS_DUP         32
%define SYS_DUP2        33
%define SYS_PAUSE       34
%define SYS_NANOSLEEP   35
%define SYS_GETITIMER   36
%define SYS_ALARM       37
%define SYS_SETITIMER   38
%define SYS_GETPID      39
%define SYS_SENDFILE    40
%define SYS_SOCKET      41
%define SYS_CONNECT     42
%define SYS_ACCEPT      43
%define SYS_SENDTO      44
%define SYS_RECVFROM    45
%define SYS_SENDMSG     46
%define SYS_RECVMSG     47
%define SYS_SHUTDOWN    48
%define SYS_BIND        49
%define SYS_LISTEN      50
%define SYS_GETSOCKNAME 51
%define SYS_GETPEERNAME 52
%define SYS_SOCKETPAIR  53
%define SYS_SETSOCKOPT  54
%define SYS_GETSOCKOPT  55
%define SYS_CLONE       56
%define SYS_FORK        57
%define SYS_VFORK       58
%define SYS_EXECVE      59
%define SYS_EXIT        60

; 고급 파일 조작
advanced_file_operations:
    push rbp
    mov rbp, rsp
    sub rsp, 144        ; stat 구조체용 공간
    
    ; 파일 열기 (O_RDWR | O_CREAT, 0644)
    mov rax, SYS_OPEN
    mov rdi, filename
    mov rsi, 0x42       ; O_RDWR | O_CREAT
    mov rdx, 0644o      ; 권한
    syscall
    
    cmp rax, 0
    jl .error
    mov r12, rax        ; 파일 디스크립터 보존
    
    ; 파일 상태 정보 가져오기
    mov rax, SYS_FSTAT
    mov rdi, r12
    lea rsi, [rbp - 144] ; stat 구조체 주소
    syscall
    
    cmp rax, 0
    jl .close_and_error
    
    ; 파일 크기 확인 (stat.st_size는 offset 48)
    mov r13, [rbp - 96]  ; st_size
    
    ; 메모리 매핑으로 파일 읽기
    mov rax, SYS_MMAP
    mov rdi, 0          ; 주소 (시스템이 결정)
    mov rsi, r13        ; 크기
    mov rdx, 1          ; PROT_READ
    mov r10, 1          ; MAP_SHARED
    mov r8, r12         ; 파일 디스크립터
    mov r9, 0           ; 오프셋
    syscall
    
    cmp rax, -1
    je .close_and_error
    mov r14, rax        ; 매핑된 주소
    
    ; 매핑된 메모리 사용 (예: 체크섬 계산)
    mov rdi, r14        ; 데이터 주소
    mov rsi, r13        ; 크기
    call calculate_checksum
    
    ; 메모리 매핑 해제
    mov rax, SYS_MUNMAP
    mov rdi, r14
    mov rsi, r13
    syscall
    
    ; 파일 닫기
    mov rax, SYS_CLOSE
    mov rdi, r12
    syscall
    
    mov rax, 0          ; 성공
    jmp .end
    
.close_and_error:
    mov rax, SYS_CLOSE
    mov rdi, r12
    syscall
    
.error:
    mov rax, -1         ; 실패
    
.end:
    mov rsp, rbp
    pop rbp
    ret

filename db '/tmp/testfile', 0

4.2 프로세스 관리

fork와 exec 시스템 호출

process_management:
    push rbp
    mov rbp, rsp
    
    ; fork() 시스템 호출
    mov rax, SYS_FORK
    syscall
    
    cmp rax, 0
    jl .fork_error      ; 에러
    je .child_process   ; 자식 프로세스
    ; 부모 프로세스 코드
    
.parent_process:
    mov r12, rax        ; 자식 PID 저장
    
    ; 자식 프로세스 대기
    mov rax, SYS_WAIT4
    mov rdi, r12        ; 자식 PID
    mov rsi, 0          ; status (NULL)
    mov rdx, 0          ; options
    mov r10, 0          ; rusage (NULL)
    syscall
    
    ; 부모 작업 계속...
    jmp .end
    
.child_process:
    ; 새 프로그램 실행
    mov rax, SYS_EXECVE
    mov rdi, program_path
    mov rsi, argv
    mov rdx, envp
    syscall
    
    ; execve가 성공하면 여기에 도달하지 않음
    ; 실패한 경우만 여기 도달
    mov rax, SYS_EXIT
    mov rdi, 1          ; 에러 코드
    syscall
    
.fork_error:
    ; fork 실패 처리
    mov rax, -1
    
.end:
    pop rbp
    ret

program_path db '/bin/ls', 0
argv:
    dq program_path
    dq ls_args
    dq 0
ls_args db '-la', 0
envp dq 0

4.3 신호 처리 (Signal Handling)

신호 핸들러 구현

; 신호 핸들러 구조체
struc sigaction
    .sa_handler    resq 1    ; 핸들러 함수 포인터
    .sa_flags      resd 1    ; 플래그
    .sa_restorer   resq 1    ; 복원 함수
    .sa_mask       resb 128  ; 신호 마스크 (sigset_t)
endstruc

signal_handler_setup:
    push rbp
    mov rbp, rsp
    sub rsp, sigaction_size
    
    ; sigaction 구조체 초기화
    lea rdi, [rbp - sigaction_size]
    mov rsi, 0
    mov rdx, sigaction_size
    call memset
    
    ; 핸들러 함수 설정
    lea rax, [rbp - sigaction_size]
    mov qword [rax + sigaction.sa_handler], signal_handler
    mov dword [rax + sigaction.sa_flags], 0x04000000  ; SA_RESTORER
    mov qword [rax + sigaction.sa_restorer], signal_restorer
    
    ; SIGINT (Ctrl+C) 핸들러 등록
    mov rax, SYS_RT_SIGACTION
    mov rdi, 2          ; SIGINT
    lea rsi, [rbp - sigaction_size]  ; new action
    mov rdx, 0          ; old action (NULL)
    mov r10, 8          ; sigset 크기
    syscall
    
    cmp rax, 0
    jl .error
    
    mov rax, 0          ; 성공
    jmp .end
    
.error:
    mov rax, -1
    
.end:
    mov rsp, rbp
    pop rbp
    ret

; 신호 핸들러 함수
signal_handler:
    ; 신호 핸들러는 재진입 가능해야 함
    ; 최소한의 작업만 수행
    
    push rax
    push rdi
    push rsi
    push rdx
    
    ; 안전한 작업만 수행 (async-signal-safe 함수만)
    mov rax, SYS_WRITE
    mov rdi, 2          ; stderr
    mov rsi, sig_msg
    mov rdx, sig_msg_len
    syscall
    
    pop rdx
    pop rsi
    pop rdi
    pop rax
    
    ; 신호 핸들러 종료
    ret

signal_restorer:
    ; 신호 처리 후 시스템이 호출하는 복원 함수
    mov rax, SYS_RT_SIGRETURN
    syscall

sig_msg db 'Signal received!', 0xA
sig_msg_len equ $ - sig_msg

4.4 네트워크 프로그래밍

소켓 프로그래밍 기초

; 소켓 주소 구조체
struc sockaddr_in
    .sin_family    resw 1    ; 주소 패밀리 (AF_INET)
    .sin_port      resw 1    ; 포트 번호 (네트워크 바이트 순서)
    .sin_addr      resd 1    ; IP 주소
    .sin_zero      resb 8    ; 패딩
endstruc

tcp_server:
    push rbp
    mov rbp, rsp
    sub rsp, sockaddr_in_size
    
    ; 소켓 생성 (AF_INET, SOCK_STREAM, 0)
    mov rax, SYS_SOCKET
    mov rdi, 2          ; AF_INET
    mov rsi, 1          ; SOCK_STREAM
    mov rdx, 0          ; protocol
    syscall
    
    cmp rax, 0
    jl .error
    mov r12, rax        ; 소켓 디스크립터 저장
    
    ; 소켓 주소 설정
    lea rdi, [rbp - sockaddr_in_size]
    mov word [rdi + sockaddr_in.sin_family], 2    ; AF_INET
    mov word [rdi + sockaddr_in.sin_port], 0x5000 ; 포트 80 (네트워크 바이트 순서)
    mov dword [rdi + sockaddr_in.sin_addr], 0     ; INADDR_ANY
    
    ; 바인드
    mov rax, SYS_BIND
    mov rdi, r12        ; 소켓
    lea rsi, [rbp - sockaddr_in_size]  ; 주소
    mov rdx, sockaddr_in_size          ; 주소 크기
    syscall
    
    cmp rax, 0
    jl .close_and_error
    
    ; 리슨
    mov rax, SYS_LISTEN
    mov rdi, r12        ; 소켓
    mov rsi, 5          ; 백로그 큐 크기
    syscall
    
    cmp rax, 0
    jl .close_and_error
    
.accept_loop:
    ; 클라이언트 연결 수락
    mov rax, SYS_ACCEPT
    mov rdi, r12        ; 서버 소켓
    mov rsi, 0          ; 클라이언트 주소 (NULL)
    mov rdx, 0          ; 주소 길이 (NULL)
    syscall
    
    cmp rax, 0
    jl .accept_loop     ; 에러시 다시 시도
    
    mov r13, rax        ; 클라이언트 소켓
    
    ; 클라이언트 처리
    call handle_client
    
    ; 클라이언트 소켓 닫기
    mov rax, SYS_CLOSE
    mov rdi, r13
    syscall
    
    jmp .accept_loop
    
.close_and_error:
    mov rax, SYS_CLOSE
    mov rdi, r12
    syscall
    
.error:
    mov rax, -1
    
.end:
    mov rsp, rbp
    pop rbp
    ret

handle_client:
    ; 매개변수: R13 = 클라이언트 소켓
    push rbp
    mov rbp, rsp
    sub rsp, 1024       ; 버퍼
    
    ; 데이터 읽기
    mov rax, SYS_READ
    mov rdi, r13
    lea rsi, [rbp - 1024]
    mov rdx, 1023
    syscall
    
    cmp rax, 0
    jle .client_end
    
    ; 응답 전송
    mov rax, SYS_WRITE
    mov rdi, r13
    mov rsi, http_response
    mov rdx, http_response_len
    syscall
    
.client_end:
    mov rsp, rbp
    pop rbp
    ret

http_response db 'HTTP/1.1 200 OK', 0xD, 0xA
              db 'Content-Type: text/html', 0xD, 0xA
              db 'Content-Length: 13', 0xD, 0xA
              db 0xD, 0xA
              db 'Hello, World!', 0
http_response_len equ $ - http_response

5. 실습 프로젝트와 최적화 ⭐⭐

5.1 종합 프로젝트: 간단한 텍스트 에디터

핵심 데이터 구조

; 텍스트 버퍼 구조
struc text_buffer
    .data           resq 1      ; 텍스트 데이터 포인터
    .capacity       resq 1      ; 전체 용량
    .size           resq 1      ; 현재 크기
    .cursor_pos     resq 1      ; 커서 위치
    .gap_start      resq 1      ; 갭 버퍼 시작
    .gap_end        resq 1      ; 갭 버퍼 끝
endstruc

; 갭 버퍼를 이용한 효율적인 텍스트 편집
text_editor:
    push rbp
    mov rbp, rsp
    sub rsp, text_buffer_size
    
    ; 텍스트 버퍼 초기화
    lea rdi, [rbp - text_buffer_size]
    call init_text_buffer
    
    ; 메인 편집 루프
.edit_loop:
    call get_key_input
    
    cmp al, 27          ; ESC
    je .exit
    cmp al, 8           ; Backspace
    je .handle_backspace
    cmp al, 127         ; Delete
    je .handle_delete
    cmp al, 13          ; Enter
    je .handle_enter
    cmp al, 32          ; 일반 문자 (32 이상)
    jae .handle_char
    
    ; 특수 키 처리
    jmp .edit_loop
    
.handle_char:
    lea rdi, [rbp - text_buffer_size]
    mov rsi, rax        ; 문자
    call insert_char
    jmp .update_display
    
.handle_backspace:
    lea rdi, [rbp - text_buffer_size]
    call delete_backward
    jmp .update_display
    
.handle_delete:
    lea rdi, [rbp - text_buffer_size]
    call delete_forward
    jmp .update_display
    
.handle_enter:
    lea rdi, [rbp - text_buffer_size]
    mov rsi, 10         ; newline
    call insert_char
    jmp .update_display
    
.update_display:
    lea rdi, [rbp - text_buffer_size]
    call render_buffer
    jmp .edit_loop
    
.exit:
    ; 정리
    lea rdi, [rbp - text_buffer_size]
    call cleanup_text_buffer
    
    mov rsp, rbp
    pop rbp
    ret

init_text_buffer:
    ; 매개변수: RDI = text_buffer*
    push rbp
    mov rbp, rsp
    push rdi
    
    ; 초기 용량 할당 (4KB)
    mov rax, SYS_MMAP
    mov rdi, 0
    mov rsi, 4096
    mov rdx, 3          ; PROT_READ | PROT_WRITE
    mov r10, 34         ; MAP_PRIVATE | MAP_ANONYMOUS
    mov r8, -1
    mov r9, 0
    syscall
    
    pop rdi
    mov [rdi + text_buffer.data], rax
    mov qword [rdi + text_buffer.capacity], 4096
    mov qword [rdi + text_buffer.size], 0
    mov qword [rdi + text_buffer.cursor_pos], 0
    mov qword [rdi + text_buffer.gap_start], 0
    mov [rdi + text_buffer.gap_end], rax
    add qword [rdi + text_buffer.gap_end], 4096
    
    pop rbp
    ret

insert_char:
    ; 매개변수: RDI = text_buffer*, RSI = character
    push rbp
    mov rbp, rsp
    
    ; 갭 버퍼에 문자 삽입
    mov rax, [rdi + text_buffer.gap_start]
    mov [rax], sil
    inc qword [rdi + text_buffer.gap_start]
    inc qword [rdi + text_buffer.size]
    inc qword [rdi + text_buffer.cursor_pos]
    
    ; 갭이 너무 작아지면 확장
    mov rax, [rdi + text_buffer.gap_end]
    sub rax, [rdi + text_buffer.gap_start]
    cmp rax, 100        ; 최소 갭 크기
    jg .end
    
    call expand_gap_buffer
    
.end:
    pop rbp
    ret

5.2 성능 최적화 기법

CPU 캐시 최적화

; 캐시 친화적인 행렬 전치
cache_friendly_transpose:
    ; 매개변수: RDI = matrix, RSI = rows, RDX = cols
    push rbp
    mov rbp, rsp
    push r12
    push r13
    push r14
    push r15
    
    mov r12, rdi        ; matrix
    mov r13, rsi        ; rows
    mov r14, rdx        ; cols
    
    ; 블록 크기 (캐시 라인에 맞춤)
    mov r15, 8          ; 8x8 블록
    
    mov r8, 0           ; block_row = 0
    
.block_row_loop:
    cmp r8, r13
    jge .done
    
    mov r9, 0           ; block_col = 0
    
.block_col_loop:
    cmp r9, r14
    jge .next_block_row
    
    ; 8x8 블록 전치
    mov r10, 0          ; i = 0
    
.inner_row_loop:
    cmp r10, r15
    jge .next_block_col
    
    mov rax, r8
    add rax, r10        ; block_row + i
    cmp rax, r13
    jge .next_block_col
    
    mov r11, 0          ; j = 0
    
.inner_col_loop:
    cmp r11, r15
    jge .next_inner_row
    
    mov rbx, r9
    add rbx, r11        ; block_col + j
    cmp rbx, r14
    jge .next_inner_row
    
    ; matrix[i][j]와 matrix[j][i] 교환
    cmp rax, rbx
    jle .skip_swap      ; 대각선 아래만 처리
    
    ; 주소 계산
    mov rcx, rax
    imul rcx, r14
    add rcx, rbx
    lea rcx, [r12 + rcx * 8]    ; matrix[i][j] 주소
    
    mov rdx, rbx
    imul rdx, r14
    add rdx, rax
    lea rdx, [r12 + rdx * 8]    ; matrix[j][i] 주소
    
    ; 교환
    mov rsi, [rcx]
    mov rdi, [rdx]
    mov [rcx], rdi
    mov [rdx], rsi
    
.skip_swap:
    inc r11
    jmp .inner_col_loop
    
.next_inner_row:
    inc r10
    jmp .inner_row_loop
    
.next_block_col:
    add r9, r15
    jmp .block_col_loop
    
.next_block_row:
    add r8, r15
    jmp .block_row_loop
    
.done:
    pop r15
    pop r14
    pop r13
    pop r12
    pop rbp
    ret

SIMD 최적화

; AVX2를 이용한 벡터 덧셈
vector_add_avx2:
    ; 매개변수: RDI = a[], RSI = b[], RDX = result[], RCX = count
    push rbp
    mov rbp, rsp
    
    ; 32바이트씩 처리 (8개의 32비트 정수)
    mov rax, rcx
    shr rax, 3          ; count / 8
    
.avx_loop:
    test rax, rax
    jz .handle_remainder
    
    vmovdqu ymm0, [rdi]     ; a[i:i+7] 로드
    vmovdqu ymm1, [rsi]     ; b[i:i+7] 로드
    vpaddd ymm2, ymm0, ymm1 ; 벡터 덧셈
    vmovdqu [rdx], ymm2     ; result[i:i+7] 저장
    
    add rdi, 32
    add rsi, 32
    add rdx, 32
    dec rax
    jmp .avx_loop
    
.handle_remainder:
    ; 나머지 원소들 처리
    and rcx, 7          ; count % 8
    
.scalar_loop:
    test rcx, rcx
    jz .end
    
    mov eax, [rdi]
    add eax, [rsi]
    mov [rdx], eax
    
    add rdi, 4
    add rsi, 4
    add rdx, 4
    dec rcx
    jmp .scalar_loop
    
.end:
    vzeroupper          ; AVX 상태 정리
    pop rbp
    ret

분기 예측 최적화

; 분기 예측을 고려한 이진 탐색
binary_search_optimized:
    ; 매개변수: RDI = array, RSI = size, RDX = target
    ; 반환값: RAX = index (없으면 -1)
    
    mov rax, 0          ; left = 0
    mov rcx, rsi        ; right = size
    dec rcx
    
.search_loop:
    cmp rax, rcx
    jg .not_found
    
    ; 중간값 계산 (오버플로우 방지)
    mov r8, rax
    add r8, rcx
    shr r8, 1           ; mid = (left + right) / 2
    
    ; array[mid] 로드
    mov r9, [rdi + r8 * 8]
    
    ; 가장 가능성 높은 경우를 먼저 (보통 target < array[mid])
    cmp rdx, r9
    jl .search_left
    jg .search_right
    
    ; 찾았음
    mov rax, r8
    ret
    
.search_left:
    ; right = mid - 1
    mov rcx, r8
    dec rcx
    jmp .search_loop
    
.search_right:
    ; left = mid + 1
    mov rax, r8
    inc rax
    jmp .search_loop
    
.not_found:
    mov rax, -1
    ret

5.3 메모리 최적화

커스텀 메모리 할당자

; 고정 크기 블록 할당자
fixed_size_allocator:
    .pool_start         dq 0
    .pool_end           dq 0
    .block_size         dq 0
    .free_list          dq 0    ; 자유 블록 연결 리스트
    .total_blocks       dq 0
    .used_blocks        dq 0

init_fixed_allocator:
    ; 매개변수: RDI = block_size, RSI = block_count
    push rbp
    mov rbp, rsp
    
    ; 블록 크기를 8바이트 경계로 정렬
    add rdi, 7
    and rdi, -8
    mov [fixed_size_allocator.block_size], rdi
    
    ; 필요한 전체 메모리 크기 계산
    imul rdi, rsi
    mov [fixed_size_allocator.total_blocks], rsi
    
    ; 메모리 할당
    mov rax, SYS_MMAP
    mov rdi, 0
    mov rsi, rdi        ; 전체 크기
    mov rdx, 3          ; PROT_READ | PROT_WRITE
    mov r10, 34         ; MAP_PRIVATE | MAP_ANONYMOUS
    mov r8, -1
    mov r9, 0
    syscall
    
    cmp rax, -1
    je .error
    
    mov [fixed_size_allocator.pool_start], rax
    add rax, rdi
    mov [fixed_size_allocator.pool_end], rax
    
    ; 자유 블록 리스트 초기화
    call init_free_list
    
    mov rax, 0          ; 성공
    jmp .end
    
.error:
    mov rax, -1
    
.end:
    pop rbp
    ret

fixed_alloc:
    ; 반환값: RAX = 할당된 블록 주소 (실패시 0)
    
    ; 자유 블록이 있는지 확인
    mov rax, [fixed_size_allocator.free_list]
    test rax, rax
    jz .no_blocks
    
    ; 첫 번째 자유 블록 제거
    mov rdx, [rax]      ; 다음 자유 블록
    mov [fixed_size_allocator.free_list], rdx
    
    ; 사용 블록 수 증가
    inc qword [fixed_size_allocator.used_blocks]
    
    ret
    
.no_blocks:
    xor rax, rax        ; NULL 반환
    ret

fixed_free:
    ; 매개변수: RDI = 해제할 블록 주소
    
    ; 유효성 검사
    mov rax, [fixed_size_allocator.pool_start]
    cmp rdi, rax
    jl .invalid
    
    mov rax, [fixed_size_allocator.pool_end]
    cmp rdi, rax
    jge .invalid
    
    ; 자유 리스트에 추가
    mov rax, [fixed_size_allocator.free_list]
    mov [rdi], rax      ; 다음 포인터 설정
    mov [fixed_size_allocator.free_list], rdi
    
    ; 사용 블록 수 감소
    dec qword [fixed_size_allocator.used_blocks]
    
.invalid:
    ret

5.4 프로파일링과 성능 측정

사이클 정확한 타이밍

; RDTSC를 이용한 정밀 타이밍
performance_timer:
    .start_time     dq 0
    .end_time       dq 0

start_timer:
    ; CPU 직렬화 (정확한 측정을 위해)
    cpuid
    
    ; 타임스탬프 읽기
    rdtsc
    shl rdx, 32
    or rax, rdx
    mov [performance_timer.start_time], rax
    ret

end_timer:
    ; 타임스탬프 읽기
    rdtsc
    shl rdx, 32
    or rax, rdx
    mov [performance_timer.end_time], rax
    
    ; CPU 직렬화
    mov eax, 0
    cpuid
    ret

get_elapsed_cycles:
    ; 반환값: RAX = 경과 사이클 수
    mov rax, [performance_timer.end_time]
    sub rax, [performance_timer.start_time]
    ret

; 성능 테스트 프레임워크
benchmark_function:
    ; 매개변수: RDI = 테스트할 함수 포인터, RSI = 반복 횟수
    push rbp
    mov rbp, rsp
    push r12
    push r13
    push r14
    
    mov r12, rdi        ; 함수 포인터
    mov r13, rsi        ; 반복 횟수
    xor r14, r14        ; 누적 시간
    
.benchmark_loop:
    test r13, r13
    jz .calculate_average
    
    call start_timer
    call r12            ; 테스트 함수 호출
    call end_timer
    
    call get_elapsed_cycles
    add r14, rax        ; 누적
    
    dec r13
    jmp .benchmark_loop
    
.calculate_average:
    mov rax, r14
    xor rdx, rdx
    div rsi             ; 평균 계산
    
    pop r14
    pop r13
    pop r12
    pop rbp
    ret

핵심 포인트 요약

제어 구조 마스터리:

  1. 플래그 레지스터 완전 이해
  2. 조건부 분기 최적화 패턴
  3. 루프 언롤링과 성능 최적화
  4. 상태 머신과 점프 테이블 활용

함수와 스택:

  1. 호출 규약 완벽 숙지 (System V vs Microsoft)
  2. 스택 프레임 구조와 최적화
  3. 재귀 함수와 꼬리 재귀 최적화
  4. 가변 인수 처리

메모리 관리:

  1. 포인터 연산과 복잡한 데이터 구조
  2. 동적 메모리 할당과 관리
  3. 캐시 친화적 프로그래밍
  4. 메모리 정렬과 최적화

시스템 프로그래밍:

  1. 시스템 호출 활용
  2. 프로세스 관리와 IPC
  3. 신호 처리와 비동기 프로그래밍
  4. 네트워크 소켓 프로그래밍

성능 최적화:

  1. SIMD 명령어 활용 (SSE, AVX)
  2. 분기 예측 최적화
  3. 캐시 계층 고려한 알고리즘
  4. 프로파일링과 성능 측정