8086 어셈블리 언어
2025. 4. 4. 00:34ㆍ어셈블리 프로그래밍
어셈블리언어 문법
- 대소문자를 구분하지 않음!
MOW와 mow는 동일!
- 어셈블리언어의 문장은 4개의 필드로 구성됨
이름(name) 연산자(operator) 오퍼랜드(operands) 설명(comment)
- 다음은 어셈블리언어의 문장을 작성할 수 있음
이름 연산자 오퍼랜드 설명
TOP: MOV AX,10 ;AX 레지스터에 10을 저장함!
- 이름 필드
-명령어의 레이블, 프로시져 이름, 변수 이름 등을 나타냄
-최대 31자
-문자, 숫자, 특수문자(?, ., @, _, $, %) 사용가능 (마침표는 맨 앞에만 사용가능함)
-빈칸은 허용 안됨
-숫자로 시작하면 안됨
cf) 불가능한 이름
TOP LOOP ;띄어 쓰기 불가능 3SSJJSS ;숫자를 맨앞에 사용하는 것은 불가능 ABC11.1 ;마침표는 첫번째에만 사용 가능 ASSEM*AS ;사용가능한 특수문자 이외는 사용불가
- 연산자 필드: 프로세서에서 수행하는 기호화된 명령어 혹은 어셈블리 지시자 등의 의사 명령어
- 오퍼랜드 필드: 연산자에 의해서 데이터를 지정하는 필드
DEC AX ;AX 레지스터의 내용을 1 감소
ADD AX,10 ;AX 레지스터의 내용을 10 더하기
- 설명 필드: 세미콜론을 활용하여서 코멘트를 덧붙임.
데이터와 변수 정의
- 10진수: 숫자+D/d(D/d는 생략 가능)
- 2진수: 숫자+B/b
- 16진수: 숫자+H/h (16진수인 경우 문자가 알파벳으로 시작하면 맨 앞에 0을 추가해줘야 함)
ex)
10110 ;십진수를 의미
1011001B ;2진수를 의미
0FFFFH /;16진수를 의미
3,567 ;숫자표현에서 콤마 사용 불가 => 3567로 변경
4FFF ;16진수를 표현할 때는 뒤에 H/h를 추가해야 함 => 4FFFH로 변경
FFFH ;16진수가 알파벳으로 시작하면 0을 맨 앞에 추가해야 함 => 0FFFH
- 문자와 문자열의 경우 홑따옴표나 큰따옴표로 표현함. (여기서는 대소문자를 구분함!)
- 대문자 'A'의 아스키코드는 41H 이기 때문에 다음과 같이 표기할 수 있음.
MOV DL,'A' ;A를 DL레지스터에 저장
MOV DL,41H ;41H, 즉 A를 DL레지스터에 저장
변수의 정의
- 변수는 데이터형을 가짐.
- 메모리의 주소를 위해 데이터 세그먼트의 옵셋 주소가 할당됨.
- 데이터형은 다음과 같은 것이 존재.
| 데이터형 | 크기 |
| DB | 1바이트 |
| DW | 2바이트 |
| DD | 4바이트 |
| DQ | 8바이트 |
| DT | 10바이트 |
- 변수를 초기화할 때 DB를 활용하면 2바이트로 크기를 할당하고 초기값을 설정해 줌.
- 이때 초기값이 필요 없을 때는 ?로 나타냄.
AB DB 10 ;초기값이 10인 바이트 변수
AC DB ? ;초기값을 설정하지 않은 바이트 변수
- DW는 2바이트, 즉 16비트로 변수의 크기를 지정함.
- 8086이 16비트 프로세서의 가장 기본이 되기 때문에 주로 DW를 사용함.
AB DW 16 ;초기값이 16인 2바이트 변수
AC DW ? ;초기값을 설정하지 않은 2바이트 변수
- 배열과 같은 경우 동일한 크기의 연속적인 메모리 변수를 나타냄.
- 배열과 같은 경우에는 다음과 같이 정의함.
AB DB 10H,20H,30H,80H ;바이트 배열로 4개의 변수로 초기화해줌
AC DW 2800, 2900,3000, 8086 ;워드(2바이트) 배열로 4개의 변수로 초기화해줌
- 문자열은 문자나 아스키코드를 활용하여 정의 가능하고, 문자열이 끝났다는 것을 프로세서가 확인하기 위해서 $(24H)로 끝내야 한다.
MSG DW 'hello',0DH, 0AH,'$' ;hello+줄바꿈(0DH:케리지 리턴, 0AH:라인 피드)+'$' => hello를 출력하고 줄바꿈
- 상수는 EQU를 활용하여서 정의할 수 있다.
CR EQU 0DH ;CR에 케리지 리턴을 의미하는 아스키코드 0DH를 상수로 지정
MOW DL, CR ;DL 레지스터에 CR을 저장해줌
8086 명령어
- 데이터 전송 명령어: 레지스터나 메모리 변수 사이의 데이터 전송을 위한 명령어
- 산술 연산 명령어: 덧셈, 뼬셈, 곱셈, 나눗셈 등의 명령어
- 논리 연산 명령어: AND, NOT, OR, XOR 등의 명령어
- 흐름 제어 명령어: 조건문, 반복문, 프로시져 호출 및 복귀 등의 프로그램 제어 명령어
MOV 명령어
- 레지스터 사이와 레지스터와 메모리 변수 사이의 데이터를 전송하는 명령어.
- 레지스터나 메모리 변수에 상수 값을 저장하는 것도 가능함.
MOV AX,DX ;DX레지스터의 내용을 AX에 저장
MOV BX,SSJ ;변수 SSJ의 내용을 BX에 저장
MOV CX,2500 ;2500을 CX레지스터 저장
- MOV를 해도 근원지 오퍼랜드의 내용은 사라지지 않는다!
- 다음은 근원지 오퍼랜드와 목적지 오퍼랜드사이에서 전송 가능한지 불가능한지에 대한 표이다.
| 근원지 오퍼랜드 | 목적지 오퍼랜드 | |||
| 일반 레지스터 | 세그먼트 레지스터 | 메모리 변수 | 상수 | |
| 일반 레지스터 | 가능 | 가능 | 가능 | 불가능 |
| 세그먼트 레지스터 | 불가능 | 가능 | ||
| 메모리 변수 | 가능 | 불가능 | ||
| 상수 | 불가능 | 가능 | ||
XCHG 명령어
- 두 레지스터와 레지스터와 메모리 변수의 내용을 변경하는 명령어.
- 메모리 변수끼리 변경하는 것은 불가능하다!
XCHG DL, AL ;AL, DL의 내용을 서로 변경
ADD와 SUB 명령어
- ADD 명령어는 두 내용을 더하거나 레지스터와 메모리 변수의 내용을 더하는 데 사용하는 명령어.
- 보통은 오퍼랜드가 두 개여서 근원지 오퍼랜드와 목적지 오퍼랜드로 구분.
- ADD 명령어는 메모리 변수와 메모리 변수끼리는 연산 불가능하다!
ADD AX, BX ;AX와 BX를 더하고 AX에 저장
ADD CL,10 ;CL의 내용에 10을 더한 뒤 CL에 저장
- SUB 명령어는 두 내용을 더하거나 레지스터와 메모리 변수의 내용을 빼는 데 사용하는 명령어.
- 보통은 오퍼랜드가 두 개여서 근원지 오퍼랜드와 목적지 오퍼랜드로 구분.
- ADD명령어와 동일하게 메모리 변수와 메모리 변수끼리는 연산 불가능하다!
SUB BX,DX ;BX의 내용에 DX의 내용을 빼고 나서 BX에 저장
SUB AX, 16 ;AX의 내용에 16을 빼고 나서 AX에 저장
| 근원지 오퍼랜드 (ADD, SUB) | 목적지 오퍼랜드 | |
| 일반 레지스터 | 메모리 변수 | |
| 일반 레지스터 | 가능 | 가능 |
| 메모리 변수 | 가능 | 불가능 |
| 상수 | 가능 | 가능 |
INC와 DEC 명령어
- INC와 DEC는 각각 1을 더하거나 빼는 명령어.
- 하나의 오패랜드만 사용한다.
INC CL ;CL의 내용을 1증가 시킴
INC SSJ ;SSJ의 내용을 1증가 시킴
DEC CL ;CL의 내용을 1감소 시킴
DEC SSJ ;SSJ의 내용을 1감소 시킴
NEG와 NOT 명령어
- NEG명령어는 레지스터나 메모리 변수의 데이터의 부호를 반대로 변경 명령어.
- 프로세서는 2의 보수를 실행하여 양수는 음수로 음수는 양수로 변환함.
NEG WRD ;WRD의 부호를 변경
NEG AX ;AX의 부호를 변경
- NOT명령어는 레지스터나 메모리 변수에 저장된 데이터의 각 비트를 반대로 변환하는 명령어
- 1의 보수를 구하는 데 활용.
NOT CX ;CX의 1의 보수를 CX에 저장
주의사항
- 모든 명령어는 메모리 변수를 근원지와 목적지 변수로 동시에 사용할 수 없다! (메모리 변수 내용을 레지스터에 저장시킨 후 연산을 적용해야 함)
- 두 개의 오퍼랜드를 사용하는 명령어에서 목적지 오퍼랜드와 근원지 오퍼랜드의 데이터형은 일치해야 한다.
.DATA
BYT DB 10
...
MOV AL,BX ;BX는 16비트, AL은 8비트 이므로 불가능
MOV CX, BYT ;CX는 16비트, BYT는 8비트 이므로 불가능
고급언어를 프로그래밍 언어로 변환
- B = A - 2 * C
MOV AX, A ;AX레지스터에 A저장
SUB AX, C ;AX에 C를 뺴고 난 후 저장
SUB AX, C ;AX에 C를 뺴고 난 후 저장
MOV B, AX ;AX레지스터의 내용을 B에 저장
- C = A * 4 - B * 2 - 10
MOV AX,A
ADD AX,AX ;A+A
ADD AX,AX ;AX가 2*A 이므로 AX+AX=4*A
SUB AX,B ;AX-B=4*A-B
SUB AX,B ;AX-B=4*A-2*B
SUB AX,10 ;AX-10=4*A-2*B-10
MOV C,AX ;AX의 내용을 C에 저장
어셈블리 프로그램 구조
- 메모리 모델 정의, 스택 크기 지정, 데이터 세그먼트 구성, 코드 세그먼트로 구성됨
메모리 모델
- 프로그램의 코드와 데이터의 크기를 나타냄.
- 메모리 모델은 프로그램 코드와 데이터가 1개의 세그먼트(64KB)에 저장될 수 있는지에 따라 5개의 모델로 나누어진다.
| 메모리 모델 | 설명 |
| SMALL | 한 세그먼트에 저장할 수 있는 코드 한 세그먼트에 저장할 수 있는 데이터 |
| MEDIUM | 한 세그먼트 이상에 저장할 수 있는 코드 한 세그먼트에 저장할 수 있는 코드 |
| COMPACT | 한 세그먼트에 저장할 수 있는 코드 한 세그먼트 이상헤 저장할 수 있는 데이터 |
| LARGE | 한 세그먼트 이상에 저장할 수 있는 코드 64KB 이상이 되지 않는 배열 |
| HUGE | 한 세그먼트 이상에 저장할 수 있는 코드와 데이터 64KB 이상이 되는 배열 |
.MODEL 메모리 모델(memory model)
- 보통 한 세그먼트에는 약 2만 개 이상의 어셈블리 언어 문장이 저장될 수 있기 때문에 대부분의 프로그램은 SMALL을 사용한다.
데이터 세그먼트
- 프로그램에서 사용하는 바이트, 워드 변수와 배열, 문자열 등의 메모리 변수를 선언.
- 프로그램에서 활용되는 모든 메모리 변수가 저장됨.
.DATA ;데이터 세그먼트
SSJ DB 10 ;메모리 변수들을 선언!
WRD DW ?
스택 세그먼트
- 어셈블리 프로그램은 여러 가지 프로시져를 사용하여 작성되기에 프로시져 호출 전후의 데이터를 유지해야 하는 레지스터나 메모리 변수의 내용은 호출된 프로시져의 코드를 실행하기 전에 스택에 저장되어야 함.
- 스택에 데이터를 저장하고 복원하는 것은 프로그램을 실행하는 중간에 발생하기 때문에 스택 영역은 데이터 세그먼트와 별도의 메모리 세그먼트에 설정되어야 함.
- 프로그램이 복잡해지면 데이터 수가 복잡해지기 때문에 스택 공간을 얼마나 사용하는지 알려 주어야 한다.
.STACK 100H ;스택 영역으로 100H, 즉 256바이트를 지정
코드 세그먼트
- 코드 세그먼트는 8086 명령어들을 사용하여 작성된 어셈블리언어의 문장들을 포함.
- 어셈블리 언어는 프로시져 단위로 구성되며, 최소 1개 이상이 존재해야 하고, 그중에 MAIN프로시져를 포함하여야 함.
.CODE 이름(name)
어셈블리 프로그램의 구조
- 메모리 모델 정의
- 스택 영역의 크기를 지정
- 메모리 변수를 사용하는 경우 데이터 세그먼트를 정의
- 코드 세그먼트에 알고리즘에 따라 코드 작성

'어셈블리 프로그래밍' 카테고리의 다른 글
| 조건문 구조(2) (0) | 2025.05.22 |
|---|---|
| 조건문 구조 (0) | 2025.05.22 |
| 플래그 래지스터&디버거 (0) | 2025.04.27 |
| 문자 입출력 (0) | 2025.04.13 |
| 8086 프로세서 (0) | 2025.03.25 |