어셈블리 언어 기초

어셈블리 언어 기초

개요

어셈블리 언어는 기계어와 1:1로 대응되는 저수준 프로그래밍 언어입니다. 프로세서가 직접 이해하는 명령어를 사람이 읽을 수 있는 형태로 표현합니다. 이 레슨에서는 x86과 ARM 어셈블리의 기초, 주요 명령어 종류, 그리고 간단한 프로그램 작성 방법을 학습합니다.

난이도: ⭐⭐⭐

선수 지식: 명령어 집합 아키텍처(ISA), CPU 구조 기초


목차

  1. 어셈블리 언어 개념
  2. x86 어셈블리 기초
  3. ARM 어셈블리 기초
  4. 산술/논리 명령어
  5. 분기 명령어
  6. 메모리 접근 명령어
  7. 간단한 어셈블리 프로그램 예제
  8. 연습 문제

1. 어셈블리 언어 개념

1.1 어셈블리 언어란?

┌─────────────────────────────────────────────────────────────────────────┐
                    프로그래밍 언어 계층 구조                             
                                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
                        고수준 언어 (High-Level)                       
                                                                      
        ┌─────────────────────────────────────────────────────┐      
           C, C++, Java, Python, JavaScript, ...                  
                                                                   
           int sum = a + b;                                        
                                                                   
           장점: 가독성, 이식성, 생산성                             
        └─────────────────────────────────────────────────────┘      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                        
                                    컴파일                              
                                                                        
    ┌─────────────────────────────────────────────────────────────────┐ 
                        어셈블리 언어 (Assembly)                       
                                                                      
        ┌─────────────────────────────────────────────────────┐      
           MOV  EAX, [a]       ; a를 EAX에 로드                    
           ADD  EAX, [b]       ; b를 더함                          
           MOV  [sum], EAX     ; 결과를 sum에 저장                 
                                                                   
           장점: 하드웨어 직접 제어, 최적화 가능                    
           단점: 이식성 없음, 생산성 낮음                          
        └─────────────────────────────────────────────────────┘      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                        
                                    어셈블                              
                                                                        
    ┌─────────────────────────────────────────────────────────────────┐ 
                        기계어 (Machine Code)                          
                                                                      
        ┌─────────────────────────────────────────────────────┐      
           A1 00 10 00 00    ; MOV EAX, [0x1000]                   
           03 05 04 10 00 00 ; ADD EAX, [0x1004]                   
           A3 08 10 00 00    ; MOV [0x1008], EAX                   
                                                                   
           CPU가 직접 실행하는 이진 코드                            
        └─────────────────────────────────────────────────────┘      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

1.2 어셈블리어의 기본 구조

┌─────────────────────────────────────────────────────────────────────────┐
                       어셈블리 명령어 형식                               
                                                                         
    [레이블:]  명령어  [피연산자1 [, 피연산자2 [, 피연산자3]]]  [; 주석] 
                                                                         
    예시:                                                                
    ┌─────────────────────────────────────────────────────────────────┐ 
                                                                      
        loop:                  ; 레이블 (점프 대상)                   
            mov  eax, ebx      ; eax = ebx                           
            add  eax, 10       ; eax = eax + 10                      
            cmp  eax, 100      ; eax와 100 비교                      
            jl   loop          ; eax < 100이면 loop로                
                                                                      
        end:                                                          
            ret                ; 반환                                
                                                                      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    구성 요소:                                                           
    ┌───────────┬─────────────────────────────────────────────────────┐ 
     레이블     메모리 주소에 이름 부여 (점프/데이터 참조용)          
    ├───────────┼─────────────────────────────────────────────────────┤ 
     명령어     CPU가 수행할 연산 (MOV, ADD, JMP )                 
    ├───────────┼─────────────────────────────────────────────────────┤ 
     피연산자   연산 대상 (레지스터, 메모리, 즉시값)                 
    ├───────────┼─────────────────────────────────────────────────────┤ 
     주석       코드 설명 (실행에 영향 없음)                         
    └───────────┴─────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

1.3 어셈블러와 어셈블 과정

┌─────────────────────────────────────────────────────────────────────────┐
│                        어셈블 과정                                       │
│                                                                         │
│    소스 파일 (.asm/.s)                                                  │
│         │                                                               │
│         ▼                                                               │
│    ┌─────────────┐                                                     │
│    │  어셈블러   │  NASM, GAS, MASM, ARMASM 등                         │
│    │ (Assembler) │                                                     │
│    └──────┬──────┘                                                     │
│           │                                                             │
│           ▼                                                             │
│    오브젝트 파일 (.o/.obj)                                              │
│         │                                                               │
│         ▼                                                               │
│    ┌─────────────┐                                                     │
│    │   링커     │  ld, link.exe 등                                     │
│    │  (Linker)  │                                                     │
│    └──────┬──────┘                                                     │
│           │                                                             │
│           ▼                                                             │
│    실행 파일 (.exe, ELF, Mach-O 등)                                    │
│                                                                         │
│    주요 어셈블러:                                                       │
│    ┌───────────────┬──────────────────────────────────────────────┐    │
│    │ NASM          │ Netwide Assembler (x86, 크로스 플랫폼)        │    │
│    │ GAS           │ GNU Assembler (AT&T 문법)                    │    │
│    │ MASM          │ Microsoft Macro Assembler (Windows)          │    │
│    │ FASM          │ Flat Assembler (x86)                         │    │
│    │ ARMASM/as     │ ARM 어셈블러                                 │    │
│    └───────────────┴──────────────────────────────────────────────┘    │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

1.4 어셈블리 문법 스타일

┌─────────────────────────────────────────────────────────────────────────┐
                    Intel 문법 vs AT&T 문법                               
                                                                         
    ┌──────────────────────────┬──────────────────────────────────────┐ 
          Intel 문법                    AT&T 문법                    
       (NASM, MASM)                    (GAS, GCC)                    
    ├──────────────────────────┼──────────────────────────────────────┤ 
     mov eax, 10               movl $10, %eax                        
     (목적지, 소스)            (소스, 목적지)                        
    ├──────────────────────────┼──────────────────────────────────────┤ 
     mov eax, ebx              movl %ebx, %eax                       
    ├──────────────────────────┼──────────────────────────────────────┤ 
     mov eax, [ebx]            movl (%ebx), %eax                     
    ├──────────────────────────┼──────────────────────────────────────┤ 
     mov eax, [ebx+ecx*4+10]   movl 10(%ebx,%ecx,4), %eax            
    ├──────────────────────────┼──────────────────────────────────────┤ 
     즉시값: 숫자              즉시값: $접두사                       
     레지스터: 이름             레지스터: %접두사                     
     크기: 명령어로 추론        크기: 접미사 (b/w/l/q)                
    └──────────────────────────┴──────────────────────────────────────┘ 
                                                                         
    AT&T 크기 접미사:                                                    
    - b (byte): 8비트                                                    
    - w (word): 16비트                                                   
    - l (long): 32비트                                                   
    - q (quad): 64비트                                                   
                                                                         
     문서에서는 Intel 문법을 주로 사용합니다.                          
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

2. x86 어셈블리 기초

2.1 x86 레지스터

┌─────────────────────────────────────────────────────────────────────────┐
│                        x86-64 레지스터                                   │
│                                                                         │
│    범용 레지스터 (64비트):                                              │
│    ┌─────────────────────────────────────────────────────────────────┐ │
│    │                                                                 │ │
│    │  64비트     32비트    16비트    8비트(H/L)    용도               │ │
│    │  ────────────────────────────────────────────────────────────   │ │
│    │  RAX        EAX       AX        AH/AL        누산기             │ │
│    │  RBX        EBX       BX        BH/BL        베이스             │ │
│    │  RCX        ECX       CX        CH/CL        카운터             │ │
│    │  RDX        EDX       DX        DH/DL        데이터             │ │
│    │  RSI        ESI       SI        SIL          소스 인덱스        │ │
│    │  RDI        EDI       DI        DIL          목적지 인덱스      │ │
│    │  RBP        EBP       BP        BPL          베이스 포인터      │ │
│    │  RSP        ESP       SP        SPL          스택 포인터        │ │
│    │  R8         R8D       R8W       R8B          범용 (x64 추가)   │ │
│    │  R9         R9D       R9W       R9B          범용 (x64 추가)   │ │
│    │  R10-R15    R10D-R15D R10W-R15W R10B-R15B   범용 (x64 추가)   │ │
│    │                                                                 │ │
│    └─────────────────────────────────────────────────────────────────┘ │
│                                                                         │
│    레지스터 크기 관계:                                                  │
│    ┌─────────────────────────────────────────────────────────────────┐ │
│    │                                                                 │ │
│    │    63                              31              15    7    0 │ │
│    │    ├───────────────────────────────┼───────────────┼────┼─────┤ │ │
│    │    │              RAX              │               │    │     │ │ │
│    │    │                               │      EAX      │    │     │ │ │
│    │    │                               │               │ AX │     │ │ │
│    │    │                               │               │ AH │ AL  │ │ │
│    │    └───────────────────────────────┴───────────────┴────┴─────┘ │ │
│    │                                                                 │ │
│    └─────────────────────────────────────────────────────────────────┘ │
│                                                                         │
│    특수 레지스터:                                                       │
│    ┌───────────┬─────────────────────────────────────────────────────┐ │
│    │ RIP       │ 명령어 포인터 (다음 명령어 주소)                     │ │
│    │ RFLAGS    │ 상태/조건 플래그                                    │ │
│    └───────────┴─────────────────────────────────────────────────────┘ │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

2.2 플래그 레지스터

┌─────────────────────────────────────────────────────────────────────────┐
│                         RFLAGS 레지스터                                  │
│                                                                         │
│    주요 상태 플래그:                                                    │
│    ┌────────┬────────────────────────────────────────────────────────┐ │
│     플래그                     설명                                  │
│    ├────────┼────────────────────────────────────────────────────────┤ │
│     CF      Carry Flag: 부호 없는 연산에서 올림/내림 발생           │
│             예: 255 + 1 = 0 (CF=1)                                  │
│    ├────────┼────────────────────────────────────────────────────────┤ │
│     ZF      Zero Flag: 결과가 0이면 1                               │
│             예: 5 - 5 = 0 (ZF=1)                                    │
│    ├────────┼────────────────────────────────────────────────────────┤ │
│     SF      Sign Flag: 결과의 최상위 비트 (부호)                    │
│             예: -1 (SF=1), 1 (SF=0)                                 │
│    ├────────┼────────────────────────────────────────────────────────┤ │
│     OF      Overflow Flag: 부호 있는 연산에서 오버플로우            │
│             예: 127 + 1 = -128 (OF=1)                               │
│    ├────────┼────────────────────────────────────────────────────────┤ │
│     PF      Parity Flag: 결과의 하위 8비트에서 1 개수가 짝수     │
│    ├────────┼────────────────────────────────────────────────────────┤ │
│     AF      Auxiliary Carry: BCD 연산용                             │
│    └────────┴────────────────────────────────────────────────────────┘ │
│                                                                         │
│    제어/시스템 플래그:                                                  │
│    ┌────────┬────────────────────────────────────────────────────────┐ │
│     DF      Direction Flag: 문자열 연산 방향 (0=증가, 1=감소)       │
│     IF      Interrupt Flag: 인터럽트 허용 여부                      │
│     TF      Trap Flag: 단일 스텝 디버깅                             │
│    └────────┴────────────────────────────────────────────────────────┘ │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

2.3 x86 기본 명령어

┌─────────────────────────────────────────────────────────────────────────┐
                        x86 기본 명령어                                   
                                                                         
    데이터 이동:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      mov  dst, src     ; dst = src                                   
      mov  eax, 10      ; eax = 10 (즉시값)                           
      mov  eax, ebx     ; eax = ebx (레지스터)                        
      mov  eax, [ebx]   ; eax = Memory[ebx] (메모리)                  
      mov  [eax], ebx   ; Memory[eax] = ebx                           
                                                                      
      movzx eax, bl     ; 0 확장 (8비트  32비트)                     
      movsx eax, bl     ; 부호 확장                                   
                                                                      
      lea  eax, [ebx+ecx*4]  ; 주소 계산 결과를 eax에                 
                             ; (메모리 접근 없음)                      
                                                                      
      xchg eax, ebx     ; eax와 ebx 교환                              
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    스택 연산:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      push eax          ; 스택에 푸시 (ESP -= 4, [ESP] = eax)         
      pop  ebx          ; 스택에서  (ebx = [ESP], ESP += 4)         
                                                                      
      스택 구조 (x86):                                                
      ┌──────────────┐ 높은 주소                                      
           ...                                                      
      ├──────────────┤                                                
         이전                                                     
      ├──────────────┤                                                
        PUSH된     ◄─── ESP (스택 포인터)                         
      ├──────────────┤                                                
         ( 공간)                                                  
      └──────────────┘ 낮은 주소                                      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

3. ARM 어셈블리 기초

3.1 ARM 레지스터

┌─────────────────────────────────────────────────────────────────────────┐
│                      ARM 레지스터 (AArch64)                              │
│                                                                         │
│    범용 레지스터:                                                       │
│    ┌─────────────────────────────────────────────────────────────────┐ │
│    │                                                                 │ │
│    │  64비트    32비트   용도                                        │ │
│    │  ─────────────────────────────────────────────────              │ │
│    │  X0-X7     W0-W7    인자 전달 / 반환값                          │ │
│    │  X8        W8       간접 결과 레지스터                          │ │
│    │  X9-X15    W9-W15   임시 (Caller-saved)                         │ │
│    │  X16-X17   W16-W17  인트라-프로시저 호출                        │ │
│    │  X18       W18      플랫폼 레지스터                             │ │
│    │  X19-X28   W19-W28  Callee-saved                                │ │
│    │  X29 (FP)  W29      프레임 포인터                               │ │
│    │  X30 (LR)  W30      링크 레지스터 (복귀 주소)                   │ │
│    │                                                                 │ │
│    └─────────────────────────────────────────────────────────────────┘ │
│                                                                         │
│    특수 레지스터:                                                       │
│    ┌───────────┬─────────────────────────────────────────────────────┐ │
│    │ SP        │ 스택 포인터                                         │ │
│    │ PC        │ 프로그램 카운터 (직접 접근 제한)                    │ │
│    │ XZR/WZR   │ 제로 레지스터 (읽으면 0, 쓰면 버림)                 │ │
│    │ NZCV      │ 조건 플래그 (N, Z, C, V)                            │ │
│    └───────────┴─────────────────────────────────────────────────────┘ │
│                                                                         │
│    ARM32 (레거시) 레지스터:                                             │
│    ┌─────────────────────────────────────────────────────────────────┐ │
│    │  R0-R12   : 범용 레지스터                                       │ │
│    │  R13 (SP) : 스택 포인터                                         │ │
│    │  R14 (LR) : 링크 레지스터                                       │ │
│    │  R15 (PC) : 프로그램 카운터                                     │ │
│    │  CPSR     : 상태 레지스터                                       │ │
│    └─────────────────────────────────────────────────────────────────┘ │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

3.2 ARM 조건 코드

┌─────────────────────────────────────────────────────────────────────────┐
                         ARM 조건 코드                                    
                                                                         
    ARM의 대부분의 명령어는 조건부 실행 가능:                             
                                                                         
    ┌────────┬────────────────┬──────────────────────────────────────┐  
     접미사      조건                     설명                       
    ├────────┼────────────────┼──────────────────────────────────────┤  
       EQ      Z == 1        Equal (같음)                           
       NE      Z == 0        Not Equal (다름)                       
       CS/HS   C == 1        Carry Set / Unsigned >=                
       CC/LO   C == 0        Carry Clear / Unsigned <               
       MI      N == 1        Minus (음수)                           
       PL      N == 0        Plus (양수 또는 0)                     
       VS      V == 1        Overflow                               
       VC      V == 0        No Overflow                            
       HI      C==1 & Z==0   Unsigned >                             
       LS      C==0 | Z==1   Unsigned <=                            
       GE      N == V        Signed >=                              
       LT      N != V        Signed <                               
       GT    N==V & Z==0     Signed >                               
       LE    N!=V | Z==1     Signed <=                              
       AL      (항상)        Always (기본값)                        
    └────────┴────────────────┴──────────────────────────────────────┘  
                                                                         
    예시 (ARM32):                                                        
    ┌─────────────────────────────────────────────────────────────────┐ 
      CMP   R0, R1       ; R0 - R1, 플래그 설정                       
      ADDEQ R2, R2, #1   ; R0 == R1이면 R2++                         
      SUBNE R2, R2, #1   ; R0 != R1이면 R2--                         
                                                                      
      ; if-else 없이 조건부 실행!                                     
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

3.3 ARM 기본 명령어

┌─────────────────────────────────────────────────────────────────────────┐
                       ARM 기본 명령어 (AArch64)                          
                                                                         
    데이터 이동:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      MOV  X0, X1         ; X0 = X1                                   
      MOV  X0, #100       ; X0 = 100 (즉시값)                         
      MVN  X0, X1         ; X0 = ~X1 (비트 반전)                      
                                                                      
      ;  즉시값 로드                                                
      MOVZ X0, #0x1234                  ; X0 = 0x1234                 
      MOVK X0, #0x5678, LSL #16         ; X0 = 0x56781234             
                                                                      
      ; PC-relative 로드                                              
      ADR  X0, label      ; X0 = label의 주소                         
      ADRP X0, label      ; 페이지 단위 주소                          
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    메모리 접근:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; Load                                                          
      LDR  X0, [X1]           ; X0 = Memory[X1]                       
      LDR  X0, [X1, #8]       ; X0 = Memory[X1 + 8]                   
      LDR  X0, [X1, X2]       ; X0 = Memory[X1 + X2]                  
      LDR  X0, [X1, X2, LSL #3] ; X0 = Memory[X1 + X2*8]              
                                                                      
      ; Store                                                         
      STR  X0, [X1]           ; Memory[X1] = X0                       
      STR  X0, [X1, #8]!      ; X1 += 8; Memory[X1] = X0 (pre-index)  
      STR  X0, [X1], #8       ; Memory[X1] = X0; X1 += 8 (post-idx)   
                                                                      
      ; 크기 지정                                                     
      LDRB W0, [X1]           ; 바이트 로드                           
      LDRH W0, [X1]           ; 하프워드 (16비트) 로드                
      LDRSW X0, [X1]          ; 부호 확장 워드 로드                   
                                                                      
      ; 다중 레지스터                                                 
      LDP  X0, X1, [X2]       ; 레지스터  로드                      
      STP  X0, X1, [X2]       ; 레지스터  저장                      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

4. 산술/논리 명령어

4.1 x86 산술/논리 명령어

┌─────────────────────────────────────────────────────────────────────────┐
                      x86 산술/논리 명령어                                
                                                                         
    산술 연산:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 덧셈                                                          
      add  eax, ebx        ; eax = eax + ebx                          
      add  eax, 10         ; eax = eax + 10                           
      adc  eax, ebx        ; eax = eax + ebx + CF (캐리 포함)         
      inc  eax             ; eax++ (CF 변경  )                    
                                                                      
      ; 뺄셈                                                          
      sub  eax, ebx        ; eax = eax - ebx                          
      sbb  eax, ebx        ; eax = eax - ebx - CF (빌림 포함)         
      dec  eax             ; eax-- (CF 변경  )                    
      neg  eax             ; eax = -eax (2의 보수)                    
                                                                      
      ; 곱셈                                                          
      mul  ebx             ; EDX:EAX = EAX * EBX (부호 없음)          
      imul eax, ebx        ; EAX = EAX * EBX (부호 있음)              
      imul eax, ebx, 10    ; EAX = EBX * 10                           
                                                                      
      ; 나눗셈                                                        
      div  ebx             ; EAX = EDX:EAX / EBX, EDX = 나머지        
      idiv ebx             ; 부호 있는 나눗셈                         
                                                                      
      주의: div/idiv 전에 EDX를 설정해야                            
      cdq                  ; EAX를 EDX:EAX로 부호 확장                
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    논리 연산:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      and  eax, ebx        ; eax = eax & ebx                          
      or   eax, ebx        ; eax = eax | ebx                          
      xor  eax, ebx        ; eax = eax ^ ebx                          
      not  eax             ; eax = ~eax                               
      test eax, ebx        ; eax & ebx (결과 저장  , 플래그만)    
                                                                      
      ; XOR을 이용한 레지스터 초기화 (최적화)                         
      xor  eax, eax        ; eax = 0 (mov eax, 0보다 효율적)          
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    시프트/회전:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      shl  eax, 2          ; eax <<= 2 (왼쪽 시프트, *4)              
      shr  eax, 1          ; eax >>= 1 (오른쪽 시프트, 논리)          
      sar  eax, 1          ; eax >>= 1 (산술 시프트, 부호 유지)       
      shl  eax, cl         ; CL 레지스터 값만큼 시프트                
                                                                      
      rol  eax, 4          ; 왼쪽으로 4비트 회전                      
      ror  eax, 4          ; 오른쪽으로 4비트 회전                    
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

4.2 ARM 산술/논리 명령어

┌─────────────────────────────────────────────────────────────────────────┐
                      ARM 산술/논리 명령어                                
                                                                         
    산술 연산:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 3-주소 형식: dst = src1 op src2                               
      ADD  X0, X1, X2        ; X0 = X1 + X2                           
      ADD  X0, X1, #100      ; X0 = X1 + 100                          
      ADDS X0, X1, X2        ; X0 = X1 + X2, 플래그 갱신              
      ADC  X0, X1, X2        ; X0 = X1 + X2 + Carry                   
                                                                      
      SUB  X0, X1, X2        ; X0 = X1 - X2                           
      SUBS X0, X1, X2        ; X0 = X1 - X2, 플래그 갱신              
      SBC  X0, X1, X2        ; X0 = X1 - X2 - !Carry                  
      NEG  X0, X1            ; X0 = -X1 (= SUB X0, XZR, X1)           
                                                                      
      MUL  X0, X1, X2        ; X0 = X1 * X2                           
      MADD X0, X1, X2, X3    ; X0 = X3 + (X1 * X2)                    
      MSUB X0, X1, X2, X3    ; X0 = X3 - (X1 * X2)                    
                                                                      
      SDIV X0, X1, X2        ; X0 = X1 / X2 (부호 있음)               
      UDIV X0, X1, X2        ; X0 = X1 / X2 (부호 없음)               
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    논리 연산:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      AND  X0, X1, X2        ; X0 = X1 & X2                           
      ORR  X0, X1, X2        ; X0 = X1 | X2                           
      EOR  X0, X1, X2        ; X0 = X1 ^ X2                           
      BIC  X0, X1, X2        ; X0 = X1 & ~X2 (비트 클리어)            
      ORN  X0, X1, X2        ; X0 = X1 | ~X2                          
      TST  X0, X1            ; X0 & X1, 플래그만 설정                 
                                                                      
      ; 시프트 연산자 ( 번째 피연산자에 적용 가능)                  
      ADD  X0, X1, X2, LSL #2  ; X0 = X1 + (X2 << 2)                  
      SUB  X0, X1, X2, LSR #1  ; X0 = X1 - (X2 >> 1)                  
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    시프트/회전:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      LSL  X0, X1, #4        ; X0 = X1 << 4 (논리 왼쪽)               
      LSR  X0, X1, #4        ; X0 = X1 >> 4 (논리 오른쪽)             
      ASR  X0, X1, #4        ; X0 = X1 >> 4 (산술 오른쪽)             
      ROR  X0, X1, #4        ; 오른쪽 회전                            
                                                                      
      LSL  X0, X1, X2        ; X0 = X1 << X2 (레지스터 값만큼)        
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

5. 분기 명령어

5.1 x86 분기 명령어

┌─────────────────────────────────────────────────────────────────────────┐
                        x86 분기 명령어                                   
                                                                         
    비교 명령어:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      cmp  eax, ebx        ; eax - ebx, 결과 버리고 플래그만 설정     
      test eax, ebx        ; eax & ebx, 결과 버리고 플래그만 설정     
                                                                      
      예시:                                                           
      cmp  eax, 0          ; eax가 0인지 확인                         
      test eax, eax        ; eax가 0인지 확인 ( 효율적)             
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    조건 점프:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 부호 없는 비교                                                
      je   label           ; Jump if Equal (ZF=1)                     
      jne  label           ; Jump if Not Equal (ZF=0)                 
      ja   label           ; Jump if Above (CF=0, ZF=0)               
      jae  label           ; Jump if Above or Equal (CF=0)            
      jb   label           ; Jump if Below (CF=1)                     
      jbe  label           ; Jump if Below or Equal (CF=1 or ZF=1)    
                                                                      
      ; 부호 있는 비교                                                
      jg   label           ; Jump if Greater (signed)                 
      jge  label           ; Jump if Greater or Equal                 
      jl   label           ; Jump if Less                             
      jle  label           ; Jump if Less or Equal                    
                                                                      
      ; 플래그 기반                                                   
      jz   label           ; Jump if Zero (= je)                      
      jnz  label           ; Jump if Not Zero (= jne)                 
      js   label           ; Jump if Sign (SF=1, 음수)                
      jns  label           ; Jump if Not Sign (SF=0)                  
      jo   label           ; Jump if Overflow                         
      jno  label           ; Jump if No Overflow                      
      jc   label           ; Jump if Carry (= jb)                     
      jnc  label           ; Jump if No Carry (= jae)                 
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    무조건 점프  호출:                                                 
    ┌─────────────────────────────────────────────────────────────────┐ 
      jmp  label           ; 무조건 점프                              
      jmp  eax             ; 레지스터에 저장된 주소로 점프            
      jmp  [eax]           ; 메모리에 저장된 주소로 점프              
                                                                      
      call function        ; 함수 호출 (복귀 주소 push  점프)       
      ret                  ; 반환 (스택에서 복귀 주소 pop)            
      ret  8               ; 반환 + 스택 정리 (8바이트 pop)           
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

5.2 ARM 분기 명령어

┌─────────────────────────────────────────────────────────────────────────┐
                        ARM 분기 명령어                                   
                                                                         
    비교 명령어:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      CMP  X0, X1          ; X0 - X1, 플래그만 설정                   
      CMP  X0, #100        ; X0 - 100                                 
      CMN  X0, X1          ; X0 + X1, 플래그만 설정 (Compare Neg.)    
      TST  X0, X1          ; X0 & X1, 플래그만                        
      TEQ  X0, X1          ; X0 ^ X1, 플래그만 (같은지 테스트)        
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    조건 분기 (AArch64):                                                 
    ┌─────────────────────────────────────────────────────────────────┐ 
      B.EQ  label          ; Branch if Equal (Z=1)                    
      B.NE  label          ; Branch if Not Equal (Z=0)                
      B.GT  label          ; Branch if Greater Than (signed)          
      B.GE  label          ; Branch if Greater or Equal               
      B.LT  label          ; Branch if Less Than                      
      B.LE  label          ; Branch if Less or Equal                  
      B.HI  label          ; Branch if Higher (unsigned >)            
      B.HS  label          ; Branch if Higher or Same (unsigned >=)   
      B.LO  label          ; Branch if Lower (unsigned <)             
      B.LS  label          ; Branch if Lower or Same (unsigned <=)    
      B.MI  label          ; Branch if Minus (N=1)                    
      B.PL  label          ; Branch if Plus (N=0)                     
      B.VS  label          ; Branch if Overflow Set                   
      B.VC  label          ; Branch if Overflow Clear                 
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    무조건 분기  호출:                                                 
    ┌─────────────────────────────────────────────────────────────────┐ 
      B    label           ; 무조건 분기                              
      BR   X0              ; 레지스터로 분기                          
                                                                      
      BL   function        ; Branch with Link                         
                           ; X30(LR) = 복귀주소, PC = function        
      BLR  X0              ; Branch with Link to Register             
                                                                      
      RET                  ; Return (= BR X30)                        
      RET  X1              ; Return (X1의 주소로)                     
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    조건 선택 (분기 없이):                                               
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 조건부 선택 (분기 페널티 없음)                                
      CSEL  X0, X1, X2, EQ   ; X0 = (EQ) ? X1 : X2                    
      CSINC X0, X1, X2, NE   ; X0 = (NE) ? X1 : X2+1                  
      CSINV X0, X1, X2, LT   ; X0 = (LT) ? X1 : ~X2                   
      CSNEG X0, X1, X2, GE   ; X0 = (GE) ? X1 : -X2                   
                                                                      
      ; 조건부 비교                                                   
      CCMP  X0, X1, #0, EQ   ; if (EQ) then CMP X0,X1 else flags=0    
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

5.3 분기 예제

┌─────────────────────────────────────────────────────────────────────────┐
                     if-else 구현 비교                                    
                                                                         
    C 코드:                                                              
    ┌─────────────────────────────────────────────────────────────────┐ 
      if (a > b) {                                                    
          c = a;                                                      
      } else {                                                        
          c = b;                                                      
      }                                                               
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    x86 어셈블리:                                                        
    ┌─────────────────────────────────────────────────────────────────┐ 
          mov  eax, [a]        ; eax = a                              
          mov  ebx, [b]        ; ebx = b                              
          cmp  eax, ebx        ; a와 b 비교                           
          jle  else_part       ; a <= b이면 else로                    
          mov  [c], eax        ; c = a                                
          jmp  end_if                                                 
      else_part:                                                      
          mov  [c], ebx        ; c = b                                
      end_if:                                                         
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    ARM 어셈블리 (AArch64):                                              
    ┌─────────────────────────────────────────────────────────────────┐ 
          LDR  W0, [X8]        ; W0 = a                               
          LDR  W1, [X9]        ; W1 = b                               
          CMP  W0, W1          ; a와 b 비교                           
          CSEL W2, W0, W1, GT  ; W2 = (a>b) ? a : b                   
          STR  W2, [X10]       ; c = W2                               
                                                                      
      ; 또는 조건부 분기 사용:                                        
          LDR  W0, [X8]                                               
          LDR  W1, [X9]                                               
          CMP  W0, W1                                                 
          B.LE else_part                                              
          STR  W0, [X10]       ; c = a                                
          B    end_if                                                 
      else_part:                                                      
          STR  W1, [X10]       ; c = b                                
      end_if:                                                         
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

6. 메모리 접근 명령어

6.1 x86 메모리 접근

┌─────────────────────────────────────────────────────────────────────────┐
                      x86 메모리 접근                                     
                                                                         
    주소 지정 형식:                                                      
    ┌─────────────────────────────────────────────────────────────────┐ 
      [base + index * scale + displacement]                           
                                                                      
      - base: 레지스터 (선택)                                         
      - index: 레지스터 (선택)                                        
      - scale: 1, 2, 4, 8 (배율)                                      
      - displacement: 상수 (선택)                                     
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    메모리 접근 예시:                                                    
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 직접 주소                                                     
      mov  eax, [0x1000]           ; eax = Memory[0x1000]             
                                                                      
      ; 레지스터 간접                                                 
      mov  eax, [ebx]              ; eax = Memory[ebx]                
                                                                      
      ; 변위                                                          
      mov  eax, [ebx + 8]          ; eax = Memory[ebx + 8]            
                                                                      
      ; 인덱스                                                        
      mov  eax, [ebx + ecx]        ; eax = Memory[ebx + ecx]          
                                                                      
      ; 스케일 인덱스 (배열 접근에 유용)                              
      mov  eax, [ebx + ecx*4]      ; array[i] (int 배열)              
                                                                      
      ; 전체 형식                                                     
      mov  eax, [ebx + ecx*4 + 100] ; struct.array[i]                 
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    크기 지정:                                                           
    ┌─────────────────────────────────────────────────────────────────┐ 
      mov  byte  [eax], 0x41       ; 1바이트 저장                     
      mov  word  [eax], 0x4142     ; 2바이트 저장                     
      mov  dword [eax], 0x41424344 ; 4바이트 저장                     
      mov  qword [rax], rbx        ; 8바이트 저장 (64비트)            
                                                                      
      ; 크기 확장 로드                                                
      movzx eax, byte [ebx]        ; 0 확장 (832비트)                
      movsx eax, byte [ebx]        ; 부호 확장                        
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    문자열 연산:                                                         
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; ESI = 소스, EDI = 목적지, ECX = 카운터                        
      movsb                ; [EDI] = [ESI], ESI++, EDI++              
      rep movsb            ; ECX번 반복 (memcpy)                      
      cmpsb                ; [ESI] [EDI] 비교                       
      scasb                ; AL과 [EDI] 비교                          
      stosb                ; [EDI] = AL (memset)                      
      lodsb                ; AL = [ESI]                               
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

6.2 ARM 메모리 접근

┌─────────────────────────────────────────────────────────────────────────┐
                      ARM 메모리 접근                                     
                                                                         
    기본 Load/Store:                                                     
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; Load                                                          
      LDR   X0, [X1]           ; X0 = Memory[X1] (64비트)             
      LDR   W0, [X1]           ; W0 = Memory[X1] (32비트)             
      LDRH  W0, [X1]           ; W0 = Memory[X1] (16비트, 0확장)      
      LDRB  W0, [X1]           ; W0 = Memory[X1] (8비트, 0확장)       
      LDRSH W0, [X1]           ; 부호 확장 하프워드                   
      LDRSB W0, [X1]           ; 부호 확장 바이트                     
                                                                      
      ; Store                                                         
      STR   X0, [X1]           ; Memory[X1] = X0                      
      STRH  W0, [X1]           ; Memory[X1] = 하위 16비트             
      STRB  W0, [X1]           ; Memory[X1] = 하위 8비트              
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    주소 지정 모드:                                                      
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 오프셋                                                        
      LDR  X0, [X1, #8]        ; X0 = Memory[X1 + 8]                  
      LDR  X0, [X1, #-8]       ; X0 = Memory[X1 - 8]                  
                                                                      
      ; 레지스터 오프셋                                               
      LDR  X0, [X1, X2]        ; X0 = Memory[X1 + X2]                 
      LDR  X0, [X1, X2, LSL #3] ; X0 = Memory[X1 + X2*8]              
                                                                      
      ; Pre-indexed (계산  베이스 갱신)                             
      LDR  X0, [X1, #8]!       ; X1 += 8; X0 = Memory[X1]             
                                                                      
      ; Post-indexed (접근  베이스 갱신)                            
      LDR  X0, [X1], #8        ; X0 = Memory[X1]; X1 += 8             
                                                                      
      ; Literal (PC-relative, 상수 로드에 유용)                       
      LDR  X0, =0x12345678     ; X0 = 0x12345678 (리터럴  사용)     
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    다중 레지스터 Load/Store:                                            
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; 레지스터                                                    
      LDP  X0, X1, [X2]        ; X0=Mem[X2], X1=Mem[X2+8]             
      STP  X0, X1, [X2]        ; Mem[X2]=X0, Mem[X2+8]=X1             
                                                                      
      ; 스택 프레임 설정 (일반적인 패턴)                              
      STP  X29, X30, [SP, #-16]!  ; 프레임/링크 레지스터 저장         
      MOV  X29, SP                ;  프레임 포인터                  
      ...                                                             
      LDP  X29, X30, [SP], #16    ; 복원                              
      RET                                                             
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

7. 간단한 어셈블리 프로그램 예제

7.1 Hello World (x86-64 Linux)

┌─────────────────────────────────────────────────────────────────────────┐
                    Hello World (x86-64 Linux, NASM)                      
                                                                         
    ; hello.asm                                                          
    ┌─────────────────────────────────────────────────────────────────┐ 
      section .data                                                   
          msg     db  "Hello, World!", 10    ; 문자열 + 개행         
          len     equ $ - msg                 ; 문자열 길이           
                                                                      
      section .text                                                   
          global _start                                               
                                                                      
      _start:                                                         
          ; write(1, msg, len)                                        
          mov     rax, 1          ; syscall: write                    
          mov     rdi, 1          ; fd: stdout                        
          mov     rsi, msg        ; 버퍼 주소                         
          mov     rdx, len        ; 길이                              
          syscall                                                     
                                                                      
          ; exit(0)                                                   
          mov     rax, 60         ; syscall: exit                     
          xor     rdi, rdi        ; 종료 코드: 0                      
          syscall                                                     
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    컴파일  실행:                                                      
    ┌─────────────────────────────────────────────────────────────────┐ 
      $ nasm -f elf64 hello.asm -o hello.o                            
      $ ld hello.o -o hello                                           
      $ ./hello                                                       
      Hello, World!                                                   
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

7.2 두 수의 합 (x86-64)

┌─────────────────────────────────────────────────────────────────────────┐
                       수의  계산 (x86-64)                            
                                                                         
    ; sum.asm - C에서 호출 가능한 함수                                   
    ┌─────────────────────────────────────────────────────────────────┐ 
      ; int add(int a, int b);                                        
      ; x86-64 호출 규약: 인자는 RDI, RSI, RDX, RCX, R8, R9          
      ;                  반환값은 RAX                                 
                                                                      
      section .text                                                   
          global add                                                  
                                                                      
      add:                                                            
          ; 프롤로그 (간단한 함수는 생략 가능)                        
          mov     eax, edi        ; eax =  번째 인자 (a)            
          add     eax, esi        ; eax +=  번째 인자 (b)           
          ret                     ; 결과는 eax에                      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    C에서 호출:                                                          
    ┌─────────────────────────────────────────────────────────────────┐ 
      // main.c                                                       
      extern int add(int a, int b);                                   
                                                                      
      int main() {                                                    
          int result = add(10, 20);                                   
          printf("10 + 20 = %d\n", result);                           
          return 0;                                                   
      }                                                               
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    컴파일:                                                              
    ┌─────────────────────────────────────────────────────────────────┐ 
      $ nasm -f elf64 sum.asm -o sum.o                                
      $ gcc main.c sum.o -o program                                   
      $ ./program                                                     
      10 + 20 = 30                                                    
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

7.3 반복문 (ARM AArch64)

┌─────────────────────────────────────────────────────────────────────────┐
                       반복문 (ARM AArch64)                               
                                                                         
    C 코드:                                                              
    ┌─────────────────────────────────────────────────────────────────┐ 
      // 배열 합계 계산                                               
      int sum_array(int *arr, int n) {                                
          int sum = 0;                                                
          for (int i = 0; i < n; i++) {                               
              sum += arr[i];                                          
          }                                                           
          return sum;                                                 
      }                                                               
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    ARM 어셈블리:                                                        
    ┌─────────────────────────────────────────────────────────────────┐ 
      // X0 = arr (배열 포인터), W1 = n (배열 크기)                   
      // 반환: W0 = 합계                                              
                                                                      
      sum_array:                                                      
          MOV     W2, #0          ; sum = 0                           
          MOV     W3, #0          ; i = 0                             
          CMP     W1, #0          ; n == 0 체크                       
          B.LE    done            ; n <= 0이면 종료                   
                                                                      
      loop:                                                           
          LDR     W4, [X0, W3, SXTW #2]  ; W4 = arr[i]                
                                         ; (i를 4배하여 오프셋)        
          ADD     W2, W2, W4      ; sum += arr[i]                     
          ADD     W3, W3, #1      ; i++                               
          CMP     W3, W1          ; i < n ?                           
          B.LT    loop            ; 참이면 반복                       
                                                                      
      done:                                                           
          MOV     W0, W2          ; 반환값 = sum                      
          RET                                                         
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    최적화 버전 (post-increment 사용):                                   
    ┌─────────────────────────────────────────────────────────────────┐ 
      sum_array_opt:                                                  
          MOV     W2, #0          ; sum = 0                           
          CBZ     W1, done        ; n == 0이면 바로 종료              
                                                                      
      loop:                                                           
          LDR     W3, [X0], #4    ; W3 = *arr++                       
          ADD     W2, W2, W3      ; sum += *arr                       
          SUBS    W1, W1, #1      ; n-- (플래그 설정)                │ │
          B.NE    loop            ; n != 0이면 반복                   
                                                                      
      done:                                                           
          MOV     W0, W2                                              
          RET                                                         
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

7.4 함수 호출과 스택 프레임

┌─────────────────────────────────────────────────────────────────────────┐
                      함수 호출과 스택 프레임                             
                                                                         
    x86-64 스택 프레임:                                                  
    ┌─────────────────────────────────────────────────────────────────┐ 
                                                                      
        높은 주소                                                     
        ┌─────────────────────┐                                       
           이전 프레임                                              
        ├─────────────────────┤                                       
           7번째+ 인자         (스택으로 전달)                      
        ├─────────────────────┤                                       
           반환 주소           ◄─── CALL에 의해 push               
        ├─────────────────────┤                                       
           저장된 RBP          ◄─── 이전 프레임 포인터              
        ├─────────────────────┤ ◄─── RBP (현재 프레임 시작)           
           지역 변수 1                                              
        ├─────────────────────┤                                       
           지역 변수 2                                              
        ├─────────────────────┤                                       
           저장된 레지스터     (callee-saved)                       
        ├─────────────────────┤ ◄─── RSP (스택 )                    
                                                                    
        낮은 주소                                                     
                                                                      
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    함수 프롤로그/에필로그 (x86-64):                                     
    ┌─────────────────────────────────────────────────────────────────┐ 
      my_function:                                                    
          ; 프롤로그                                                  
          push    rbp             ; 이전 프레임 포인터 저장           
          mov     rbp, rsp        ;  프레임 설정                    
          sub     rsp, 32         ; 지역 변수 공간 할당               
          push    rbx             ; callee-saved 레지스터 저장        
                                                                      
          ; 함수 본문                                                 
          ...                                                         
                                                                      
          ; 에필로그                                                  
          pop     rbx             ; 레지스터 복원                     
          mov     rsp, rbp        ; 스택 정리                         
          pop     rbp             ; 프레임 포인터 복원                
          ret                                                         
                                                                      
      ; 또는 leave 명령어 사용                                        
          leave                   ; mov rsp, rbp + pop rbp            
          ret                                                         
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
    ARM AArch64 함수:                                                    
    ┌─────────────────────────────────────────────────────────────────┐ 
      my_function:                                                    
          ; 프롤로그                                                  
          STP     X29, X30, [SP, #-32]!  ; FP, LR 저장                
          MOV     X29, SP                 ;  프레임 설정            
          STP     X19, X20, [SP, #16]     ; callee-saved 저장         
                                                                      
          ; 함수 본문                                                 
          ...                                                         
                                                                      
          ; 에필로그                                                  
          LDP     X19, X20, [SP, #16]     ; 레지스터 복원             
          LDP     X29, X30, [SP], #32     ; FP, LR 복원               
          RET                                                         
    └─────────────────────────────────────────────────────────────────┘ 
                                                                         
└─────────────────────────────────────────────────────────────────────────┘

8. 연습 문제

기초 문제

  1. 어셈블리 언어와 기계어의 관계를 설명하시오.

  2. x86에서 다음 레지스터의 용도를 설명하시오:

  3. (a) EAX
  4. (b) ESP
  5. (c) EIP/RIP

  6. Intel 문법과 AT&T 문법의 주요 차이점 2가지를 쓰시오.

x86 어셈블리 문제

  1. 다음 x86 어셈블리 코드의 실행 후 EAX의 값은? asm mov eax, 10 mov ebx, 5 add eax, ebx shl eax, 1

  2. 다음 C 코드를 x86-64 어셈블리로 변환하시오: c int abs(int x) { if (x < 0) return -x; return x; }

ARM 어셈블리 문제

  1. ARM에서 조건부 실행의 장점을 설명하시오.

  2. 다음 ARM 코드의 실행 후 X0의 값은? asm MOV X0, #10 MOV X1, #3 MUL X0, X0, X1 SUB X0, X0, #5

메모리 접근 문제

  1. x86에서 [EBX + ECX*4 + 100] 주소 지정의 각 요소가 의미하는 것을 설명하시오.

  2. ARM의 pre-indexed와 post-indexed 주소 지정의 차이를 예시와 함께 설명하시오.

심화 문제

  1. 다음 C 코드를 x86-64 또는 ARM AArch64 어셈블리로 변환하시오: c int factorial(int n) { int result = 1; for (int i = 2; i <= n; i++) { result *= i; } return result; }
정답 1. 어셈블리 언어는 기계어(0과 1)를 사람이 읽을 수 있는 니모닉(ADD, MOV 등)으로 표현한 것입니다. 어셈블러가 어셈블리 코드를 기계어로 1:1 변환합니다. 2. 레지스터 용도: - (a) EAX: 누산기, 산술 연산 결과 저장, 함수 반환값 - (b) ESP: 스택 포인터, 스택의 최상단 주소 - (c) EIP/RIP: 명령어 포인터, 다음 실행할 명령어의 주소 3. Intel vs AT&T: - 피연산자 순서: Intel은 (dst, src), AT&T는 (src, dst) - 접두사: Intel은 없음, AT&T는 레지스터에 %, 즉시값에 $ 4. 코드 실행 결과: - mov eax, 10 → eax = 10 - add eax, ebx → eax = 15 - shl eax, 1 → eax = 30 5. abs 함수 (x86-64): ```asm abs: mov eax, edi ; eax = x test eax, eax ; x 부호 확인 jns positive ; x >= 0이면 점프 neg eax ; x = -x positive: ret ``` 6. ARM 조건부 실행 장점: - 짧은 분기 시 파이프라인 플러시 방지 - 코드 크기 감소 - 분기 예측 실패 페널티 없음 7. ARM 코드 결과: - MOV X0, #10 → X0 = 10 - MUL X0, X0, X1 → X0 = 30 - SUB X0, X0, #5 → X0 = 25 8. x86 주소 지정 요소: - EBX: 베이스 레지스터 (배열 시작 주소) - ECX: 인덱스 레지스터 (배열 인덱스) - 4: 스케일 (요소 크기, int = 4바이트) - 100: 변위 (구조체 내 오프셋) 9. ARM 인덱싱: - Pre-indexed `LDR X0, [X1, #8]!`: X1 += 8 후 로드 - Post-indexed `LDR X0, [X1], #8`: 로드 후 X1 += 8 10. factorial (x86-64): ```asm factorial: mov eax, 1 ; result = 1 cmp edi, 1 jle done ; n <= 1이면 종료 mov ecx, 2 ; i = 2 loop: imul eax, ecx ; result *= i inc ecx ; i++ cmp ecx, edi jle loop ; i <= n이면 반복 done: ret ```

다음 단계


참고 자료

to navigate between lessons