어셈블리어 기초: 소스 프로그램부터 실행까지

이 문서는 어셈블리어 기초 개념을 설명하며, 소스 코드 작성부터 실행 가능한 프로그램으로 변환되는 과정을 다룹니다.

소스에서 실행 파일까지의 과정

어셈블리 프로그램 개발 과정은 다음 단계로 구성됩니다:

  1. 어셈블리 소스 코드 작성
  2. 컴파일러를 사용한 컴파일 및 링크
  3. 생성된 실행 파일 실행

실행 파일은 프로그램 코드와 데이터, 그리고 관련 설명 정보(프로그램 크기, 메모리 요구량 등)를 포함합니다.

기본 소스 프로그램 구조

기본적인 소스 프로그램 예시:

assume cs:program_segment

program_segment segment
    mov cx, 0abcdH
    mov dx, 01234H
    add cx, dx
    add cx, cx
    
    mov ax, 4c00H
    int 21H
program_segment ends

end

가상 지시어

어셈블리어에는 두 가지 지시어가 있습니다:

  • 실제 기계어로 변환되는 어셈블리 지시어
  • 컴파일러가 처리하는 가상 지시어(의사 지시어)

주요 가상 지시어:

  • segmentends: 세그먼트 정의
  • end: 프로그램 종료 표시
  • assume: 세그먼트 레지스터 연결

컴파일 및 링킹

컴파일은 다음 명령으로 수행:

masm 파일명;

링킹은 다음 명령으로 수행:

link 파일명;

링커의 역할:

  1. 여러 오브젝트 파일 결합
  2. 라이브러리 함수 연결
  3. 실행 가능한 정보 생성

프로그램 실행 및 디버깅

프로그램 실행은 파일명 직접 입력으로 가능합니다. 디버깅은 debug.exe를 사용하여 단계별 실행 추적이 가능합니다.

[BX]와 loop 명령어

메모리 접근 방법:

mov si, [di]      ; DI가 가리키는 메모리 내용을 SI에 저장
mov bl, [si+5]    ; SI+5 위치의 바이트를 BL에 저장

loop 명령어 형식:

loop 레이블

loop 명령어는 CX 레지스터 값을 1 감소시키고, CX가 0이 아닌 경우 지정된 레이블로 점프합니다.

loop 사용 예시

assume cs:calc

calc segment
    mov ax, 3
    mov cx, 10
repeat:
    add ax, ax
    loop repeat
    
    mov ax, 4c00H
    int 21H
calc ends
end

메모리 주소 지정 방법

어셈블리에서는 다양한 메모리 주소 지정 방식을 제공합니다:

  1. 직접 주소 지정: [상수]
  2. 레지스터 간접 주소 지정: [레지스터]
  3. 상대 주소 지정: [레지스터+상수]
  4. 기반 인덱스 주소 지정: [bx+si]
  5. 상대 기반 인덱스 주소 지정: [bx+si+상수]

세그먼트 접두사

메모리 접근 시 명시적으로 세그먼트를 지정할 수 있습니다:

mov ax, ds:[bx]    ; DS 세그먼트 사용
mov ax, es:[di]    ; ES 세그먼트 사용

여러 세그먼트 사용

프로그램을 구조화하기 위해 코드, 데이터, 스택을 별도 세그먼트로 분리할 수 있습니다:

assume cs:code, ds:data, ss:stack

data segment
    dw 1234H, 5678H, 9abcH, 0defH
data ends

stack segment
    dw 0, 0, 0, 0, 0, 0, 0, 0
stack ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax
    mov sp, 10H
    
    mov bx, 0
    mov cx, 4
s:  push [bx]
    add bx, 2
    loop s
    
    mov bx, 0
    mov cx, 4
s2: pop [bx]
    add bx, 2
    loop s2
    
    mov ax, 4c00H
    int 21H
code ends
end start

비트 연산과 문자 처리

and와 or 명령어를 사용한 비트 조작:

mov al, 01010101B
and al, 11110000B    ; 상위 4비트만 유지
mov al, 01010101B
or al, 00001111B     ; 하위 4비트를 1로 설정

문자 데이터는 작은따옴표로 표현할 수 있습니다:

mov al, 'A'    ; mov al, 41H와 동일

SI와 DI 레지스터 활용

SI(소스 인덱스)와 DI(목적지 인덱스)는 메모리 주소 지정에 사용됩니다:

mov si, 0
mov di, 16
mov cx, 8
copy_loop:
    mov ax, [si]
    mov [di], ax
    add si, 2
    add di, 2
    loop copy_loop

고급 주소 지정 방식

여러 레지스터를 조합한 주소 지정:

mov ax, [bx+si]      ; BX와 SI 값의 합으로 주소 지정
mov ax, [bx+di+5]    ; BX, DI, 상수 5의 합으로 주소 지정
mov ax, 10[bx][si]   ; 위와 동일한 다른 표기법

실용적인 예제

문자열 대소문자 변환:

data segment
    db 'Programming'
    db 'Language'
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov bx, 0
    mov cx, 11
    
to_upper:
    mov al, [bx]
    and al, 11011111B
    mov [bx], al
    inc bx
    loop to_upper
    
    mov bx, 11
    mov cx, 8
    
to_lower:
    mov al, [bx]
    or al, 00100000B
    mov [bx], al
    inc bx
    loop to_lower
    
    mov ax, 4c00H
    int 21H
code ends
end start

배열 데이터 처리:

assume cs:main_prog, ds:array_data

array_data segment
    dw 100, 200, 300, 400, 500
array_data ends

main_prog segment
start:
    mov ax, array_data
    mov ds, ax
    mov bx, 0
    mov si, 0
    mov cx, 5
    
sum_array:
    mov ax, [bx+si]
    add [sum], ax
    add si, 2
    loop sum_array
    
    mov ax, 4c00H
    int 21H
main_prog segment
end start

태그: Assembly x86 masm programming low-level

9월 3일 21:05에 게시됨