컴퓨터 하드웨어와 기본 구조
컴퓨터는 중앙처리장치(CPU), 메모리, 버스 시스템으로 구성됩니다. 모든 명령어와 데이터는 메모리나 저장장치에 이진수 형태로 저장됩니다. 8086 프로세서는 20비트 주소버스를 통해 1MB(2^20)의 메모리 공간에 접근할 수 있습니다.
저장장치 주소 체계
메모리는 일련의 저장 단위로 구성되며, 각 단위는 고유한 물리적 주소를 가집니다. 주소버스의 폭은 접근 가능한 메모리 범위를 결정하며, 데이터버스는 CPU와 메모리 간 데이터 전송 속도를 결정합니다.
레지스터 체계
8086 CPU는 14개의 레지스터를 제공합니다. 범용 레지스터인 AX, BX, CX, DX는 각각 16비트이며, 상위 8비트와 하위 8비트로 분할 사용할 수 있습니다.
; 레지스터 사용 예제
mov 누산기, 0x1234 ; AX 레지스터에 즉시값 저장
mov 기준, 누산기 ; BX 레지스터에 AX 값 복사
add 누산기, 기준 ; AX = AX + BX
세그먼트 레지스터
CS(코드세그먼트), DS(데이터세그먼트), SS(스택세그먼트), ES(추가세그먼트)는 메모리 세그먼트의 기준 주소를 저장합니다. 물리적 주소는 '세그먼트주소 × 16 + 오프셋' 공식으로 계산됩니다.
기본 명령어 집합
데이터 전송 명령어
; MOV 명령어 활용
mov 기준, 0x1000 ; BX에 세그먼트 주소 로드
mov 세그먼트레지스터, 기준 ; DS에 세그먼트 주소 설정
mov 누산기, [0] ; DS:0 주소의 데이터를 AX로 로드
mov [0], 데이터레지스터 ; DX 값을 DS:0 주소에 저장
산술 연산 명령어
; ADD 명령어 활용
add 누산기, 0x10 ; AX에 16 추가
add 기준, 누산기 ; BX = BX + AX
메모리 접근 기법
직접 주소 지정 방식
대괄호 표기법을 사용하여 메모리 주소를 지정합니다. [오프셋] 형태로 사용하며, 세그먼트 주소는 DS 레지스터가 기본적으로 제공합니다.
레지스터 간접 주소 지정
; BX를 주소 포인터로 사용
mov 기준, 0x0200 ; 오프셋 주소 설정
mov 누산기, [기준] ; DS:BX 주소의 데이터 로드
변위 주소 지정 방식
; 상대 주소 계산
mov 누산기, [기준+0x10] ; BX+16 오프셋 주소 접근
mov 누산기, [기준+시작인덱스+0x20] ; 복합 변위 주소
스택 메커니즘
8086 CPU는 PUSH와 POP 명령어를 통해 스택 구조를 지원합니다. SS:SP 레지스터 쌍이 스택 최상위 주소를 가리킵니다.
; 스택 초기화 및 사용
mov 기준, 0x1000
mov 스택세그먼트, 기준
mov 스택포인터, 0x0020 ; 스택 탑 설정
push 누산기 ; AX 값을 스택에 푸시
pop 데이터레지스터 ; 스택에서 DX로 팝
디버그 도구 활용
기본 명령어
R: 레지스터 내용 조회 및 수정D: 메모리 덤프 (예:D 0x1000:0)E: 메모리 직접 수정 (예:E 0x1000:0 0x12 0x34)U: 기계어를 어셈블리어로 디스어셈블A: 어셈블리어로 메모리에 명령어 작성T: 단일 명령어 실행G: 지정 주소까지 실행P: 프로시저 스킵 실행
어셈블리 프로그램 구조
세그먼트 정의
코드영역 segment
assume cs:코드영역, ds:데이터영역, ss:스택영역
시작점:
; 데이터 세그먼트 초기화
mov 누산기, 데이터영역
mov 데이터세그먼트, 누산기
; 주 프로그램 로직
mov 카운터, 5
루프레이블:
; 반복 처리 코드
loop 루프레이블
; 프로그램 종료
mov 누산기, 0x4C00
int 0x21
코드영역 ends
end 시작점
가명(pseudo) 지시어
db: 바이트 단위 데이터 정의dw: 워드(2바이트) 단위 데이터 정의dd: 더블워드(4바이트) 데이터 정의dup: 데이터 반복 정의 (예:db 5 dup(0))
루프 제어 구조
LOOP 명령어는 CX 레지스터와 결합하여 반복문을 구현합니다. CX 값이 0이 될 때까지 지정된 레이블로 점프합니다.
; 1부터 10까지 합계 계산
mov 누산기, 0
mov 카운터, 10
mov 기준, 1
합계루프:
add 누산기, 기준
inc 기준
loop 합계루프
; 결과: AX = 55
고급 주소 지정 모드
SI/DI 변址 레지스터 활용
; 문자열 복사 예제
mov 원본인덱스, 0 ; SI
mov 목적인덱스, 16 ; DI
mov 카운터, 8
복사루프:
mov 누산기, [기준+원본인덱스]
mov [기준+목적인덱스], 누산기
add 원본인덱스, 2
add 목적인덱스, 2
loop 복사루프
기저-변址 복합 주소
; 복합 주소 계산
mov 누산기, [기준+원본인덱스+0x10] ; BX+SI+상수
산술 연산 고급 명령어
곱셈과 나눗셈
; MUL 명령어 (무기호 곱셈)
mov 알레지스터, 100
mov 블레지스터, 50
mul 블레지스터 ; AX = AL × BL
; DIV 명령어 (무기호 나눗셈)
mov 누산기, 1000
mov 블레지스터, 10
div 블레지스터 ; AL = AX ÷ BL(몫), AH = 나머지
ADC/SBB 명령어
여러 정밀도 연산을 위한 명령어로, 이전 연산의 캐리/빌로우 플래그를 포함합니다.
; 32비트 덧셈
mov 누산기, 0x1234
mov 데이터레지스터, 0x5678
add 기준, 0x9ABC
adc 누산기, 0x0DEF ; 상위 워드에 캐리 포함
플래그 레지스터와 조건부 실행
주요 플래그 비트
- ZF: 연산 결과가 0이면 설정
- CF: 캐리/빌로우 발생 시 설정 (무기호 연산)
- OF: 오버플로우 발생 시 설정 (기호 연산)
- SF: 연산 결과 부호 비트
- PF: 결과의 짝수 패리티
- DF: 문자열 방향 제어
조건부 점프 명령어
; JZ/JNZ (Zero Flag)
cmp 누산기, 0
je 같을때실행 ; ZF=1 시 점프
; JC/JNC (Carry Flag)
cmp 기준, 0xFFFF
jb 작을때실행 ; CF=1 시 점프 (아래)
서브루틴 설계
CALL/RET 메커니즘
; 서브루틴 호출 예제
main:
mov 매개변수, 5
call 팩토리얼계산
; 결과는 누산기에 반환
팩토리얼계산:
push 기준 ; 레지스터 보존
mov 기준, 매개변수
mov 카운터, 기준
dec 카운터
mov 누산기, 기준
계산루프:
mul 카운터
loop 계산루프
pop 기준 ; 레지스터 복원
ret ; 호출 지점으로 복귀
매개변수 전달 방식
- 레지스터 방식: 값을 레지스터에 직접 로드
- 메모리 방식: 데이터 영역에 매개변수 배치
- 스택 방식: PUSH로 스택에 전달
문자열 및 화면 처리
문자 변환 테이블
; 16진수를 ASCII로 변환
변환테이블 db '0123456789ABCDEF'
mov 기준, 변환테이블
mov 알레지스터, 0x0A ; 변환할 값
mov 원본인덱스, 알레지스터
mov 누산기, [기준+원본인덱스] ; 'A' 문자 획득
비디오 메모리 조작
텍스트 모드에서 0xB800:0000 주소가 화면 버퍼입니다. 문자와 속성 바이트를交替로 작성합니다.
; 화면 중앙에 문자 출력
mov 누산기, 0xB800
mov 엑스트라세그먼트, 누산기
mov 목적인덱스, (80*12 + 40) * 2 ; 화면 중앙 오프셋
mov 알레지스터, 'A'
mov 엑스트라세그먼트:[목적인덱스], 알레지스터
mov 알레지스터, 0x07 ; 흰색 속성
mov 엑스트라세그먼트:[목적인덱스+1], 알레지스터
인터럽트 처리
BIOS/DOS 인터럽트
; 프로그램 종료
mov 누산기, 0x4C00
int 0x21 ; DOS 21h 인터럽트
; 화면 클리어 (BIOS)
mov 누산기, 0x0600 ; 스크롤 윈도우 기능
mov 카운터, 0x07 ; 속성
mov 데이터레지스터, 0x184F ; 화면 크기
int 0x10 ; BIOS 10h 인터럽트
고급 기법
시프트 연산
; 논리 시프트
mov 알레지스터, 0b10010000
shr 알레지스터, 1 ; 0b01001000, CF=0
; 회전 시프트
mov 알레지스터, 0b10010001
ror 알레지스터, 1 ; 0b11001000, CF=1
구조화된 프로그래밍
코드, 데이터, 스택을 분리된 세그먼트로 정의하여 모듈화된 프로그램을 작성합니다.
데이터영역 segment
배열 dw 1, 2, 3, 4, 5
결과 dd 0
데이터영역 ends
스택영역 segment stack
db 64 dup(0)
스택영역 ends
코드영역 segment
assume cs:코드영역, ds:데이터영역, ss:스택영역
시작점:
; 초기화 및 메인 로직
mov 누산기, 0x4C00
int 0x21
코드영역 ends
end 시작점
최적화 및 디버깅 팁
- 레지스터 할당을 효율적으로 계획하여 메모리 접근 최소화
- 루프에서 불필요한 명령어 제거
- 플래그를 활용한 조건부 실행으로 분기 예측 개선
- Debug의 T/P/G 명령어로 단계별 실행 및 브레이크포인트 설정
- INT 3 소프트 브레이크포인트 활용
어셈블리 언어는 하드웨어에 직접 접근하는 강력한 도구이며, 레지스터와 메모리를 직접 제어함으로써 최고의 성능을 추구할 수 있습니다. 위 가이드를 통해 기본 개념부터 고급 기법까지 단계적으로 학습할 수 있습니다.