[System] 어셈블리어 명령
(1) 어셈블리어 기본 명령
-
CPU 종류에 따라 동작 가능한 작동 코드가 다른 경우도 있지만, 대부분 비슷
1-1. 산술 연산 명령
-
메모리나 범용 레지스터에 위치한 바이트, 워드, 더블 워드 정수에서 기본적 정수 계산
ADD (add)
-
제1피연산자와 제2피연산자 값을 더한 결과 값을 제1피연산자에 저장
형식 | ADD | [제1피연산자], | [제2피연산자] |
사용 예 | ADD | AL | 4 |
AL이 원래 3이었다면, 명령 실행 후에는 7이 됨 |
SUB (Subtract)
-
제1피연산자에서 제2피연산자 값을 뺀 결과 값을 제1피연산자에 저장
형식 | SUB | [제1피연산자], | [제2피연산자] |
사용 예 | SUB | AL | 4 |
AL이 원래 7이었다면, 명령 실행 후에는 3이 됨 |
CMP (Compare)
-
데이터의 두 값을 비교할 때 사용
-
예로 'cmp a, b'는 a에서 b를 뺀 값이 0이면 참이 됨
형식 | CMP | [제1피연산자], | [제2피연산자] |
사용 예 | CMP | AL | 4 |
AL이 원래 7이었다면, 명령 실행 후에는 3이 되고 0이 아니므로 거짓이 됨 |
기타 산술 연산 명령
-
ADD, SUB, CMP 외 기타 산술 연산 명령은 다음과 같다.
명령 | 설명 | |
ADC | ADd with Carry | 캐리를 포함한 덧셈 수행 |
SBB | SuBtraction with Borrow | 캐리를 포함한 뺄셈 수행 |
DEC | DECrement | 피연산자 내용을 1 감소 시킴 |
NEG | Change Sign | 피연산자 2의 보수로 부호를 반전 |
INC | INCrement | 피연산자 내용을 1 증가 시킴 |
AAA | ASCII Adjust for Add | 덧셈 결과의 AL 값을 UNPACK 10진수로 보정 |
DAA | Decimal Adjust for Add | 덧셈 결과의 AL 값을 PACK 10진수로 보정 |
AAS | ASCII Adjust For Subtact | 뺄셈 결과의 AL 값을 UNPACK 10진수로 보정 |
DAS | Decimal Adjust for Subtract | 뺼셈 결과의 AL 값을 PACK 10진수로 보정 |
MUL | MUltipLy (Unsigned) | AX와 피연산자의 곱셈 결과를 AX 또는 DX:AX에 저장 |
IMUL | Integer MULtiply (Signed) | 부호화된 곱셈 수행 |
AAM | ASCII Adjust for Multiply | 곱셈 결과의 AX 값을 UNPACK 10진수로 보정 |
DIV | DIVide (Unsigned) | AX 또는 DX:AX 내용을 피연산자로 나누고, 몫은 AL 또는 AX에 저장한 다음 나머지는 AH 또는 DX에 저장 |
IDIV | Integer DIVide (Signed) | 부호화된 나눗셈 수행 |
AAD | ASCII Adjust for Divide | 나눗셈 결과 AX 값을 UNPACK 10진수로 보정 |
CBW | Convert Byte to Word | AL의 바이트 데이터를 부호 비트를 포함해 AX 워드로 확장 |
CWD | Convert Word to Double word | AX 워드 데이터를 부호를 포함해 DX:AX의 더블 워드로 변환 |
1-2. 데이터 전송 명령
-
메모리, 범용 레지스터, 세그먼트 레지스터로 참조되는 주소에 들어 있는 데이터 전송
-
조건 이동, 스택 접근, 데이터 변환 같은 특정 연산도 수행
MOV (Move)
-
데이터를 이동할 때 사용
-
제1피연산자는 데이터 이동의 목적지이고, 제2피연산자는 이동의 대상
-
제1피연산자는 레지스터와 메모리가 될 수 있고, 제2피연산자는 수치, 레지스터, 메모리 등이 될 수 있음
-
하지만 메모리에서 메모리로 이동은 불가능
형식 | MOV | [제1피연산자], | [제2피연산자] |
사용 예 | MOV | AX, | [BP+8] |
BP의 주소에 8 더한 주소에 있는 데이터 값을 AX에 대입 |
위 그림에서 BP의 현재 값이 0x10000004라면, BP+8은 0x1000000C가 된다.
그리고 0x1000000C에 있는 값이 1,024이므로 AX에는 1024가 입력된다.
PUSH (Push)
-
스택에 데이터를 삽입할 때 사용
형식 | PUSH | [제1피연산자] |
위 그림과 같이 스택은 커지고, 스택 포인터는 데이터 크기만큼 감소한다.
POP (Pop)
-
스택에서 데이터를 삭제할 때 사용
-
스택에서 삭제된 명령은 반환 값으로 받아 사용 가능
형식 | POP | [제1피연산자] |
위 그림과 같이 스택 포인터는 삭제하는 데이터 크기만큼 증가한다.
LEA (Load effective address to register)
-
데이터 값을 이동할 때 사용하며, MOV와 조금 다름
-
MOV와 LEA 명령의 공통점은 제1피연산자는 데이터 이동의 목적지지만, 제2피연산자에서 추가 연산을 처리하는 방식이 다름
-
예로 제2피연산자에 'BP+4'가 있을 때 MOV 명령은 'BP+4'를 주소 값 하나로 처리하지만, LEA 명령은 'BP'만 주소 값으로 인식하고 +4는 BP 주소 값의 추가 연산으로 처리
형식 | LEA | [제1피연산자] | [제2피연산자] |
사용 예 | LEA | AX, | [BP+4] |
BP의 현재 값이 0x10000004라면, MOV 명령처럼 BP+4인 0x10000008의 주소 값을 가져오는 것이 아닌 0x10000004의 주소에 있는 값에 4를 더해 AX에 대입 |
기타 데이터 전송 명령
-
MOV, PUSH, POP, LEA 외 기타 데이터 전송 명령은 다음과 같다.
명령 | 설명 | |
XCHG | Exchange Register / Memory with Register |
첫 번째 피연산자와 두 번째 피연산자를 바꿈 |
IN | Input from AL / AX to Fixed port |
피연산자로 지시한 포트로 AX에 데이터를 입력 |
OUT | Output from AL / AX to Fixed port |
피연산자가 지시한 포트로 AX의 데이터 출력 |
XLAT | Translate byte to AL | BX:AL이 지시한 테이블 내용을 AL로 로드 |
LES | Load Pointer to ES | LEA 명령과 유사한 방식으로 다른 ES 데이터의 주소 내용을 참조할 때 사용 |
LAHF | Load AH with Flags | 플래그 내용을 AH의 특정 비트로 로드 |
SAHF | Store AH into Flags | AH의 특정 비트를 플래그 레지스터로 전송 |
PUSHF | Push Flags | 플래그 레지스터 내용을 스택에 삽입 |
POPF | Pop Flags | 스택에 저장된 플래그 레지스터 값 삭제 |
1-3. 논리 명령
-
연산 부호가 논리 연산을 지정
-
자리 옮김, 논리합(OR), 논리곱(AND), 기호 변환 등이 있음
AND (And)
-
대응되는 비트가 둘 다 1일 때만 결과가 1이고, 그 외는 모두 0
형식 | AND | [제1피연산자], | [제2피연산자] |
사용 예 | AND | AX, | 10h |
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다. 0x10h는 1010이므로 명령을 수행한 후 AX 값은 1000이 된다. |
OR (Or)
-
대응되는 비트 중 하나만 1이어도 결과가 1이고, 둘 다 0일 때만 0이 됨
형식 | OR | [제1피연산자], | [제2피연산자] |
사용 예 | OR | AX, | 10h |
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다. 0x10h는 1010이므로 명령을 수행한 후 AX 값은 1010이 된다. |
XOR (Exclusive Or)
-
대응되는 비트 중에서 한 비트가 1이고 다른 비트가 0이면 결과가 1이 됨
-
비트 두 개가 모두 0 또는 1일 때는 0이 됨
형식 | XOR | [제1피연산자], | [제2피연산자] |
사용 예 | XOR | AX, | 10h |
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다. 0x10h는 1010이므로 명령을 수행한 후 AX 값은 0010이 된다. |
NOT (Invert)
-
피연산자 1의 보수를 구하는 작동 코드로 각 비트를 반전시켜 줌
형식 | NOT | [제1피연산자] |
사용 예 | NOT | AX |
AX 값이 0x08h일 때, 이를 2진수로 표현하면 1000이 된다. 명령을 수행한 후 AX 값은 0111이 된다. |
TEST (And function to flags, no result)
-
CMP 명령처럼 데이터의 두 값을 비교할 때 사용
-
단 CMP처럼 제1피연산자에서 제2피연산자 값을 빼는 과정이 없음
-
즉, 데이터 변경 없이 단순 비교만 함
형식 | TEST | [제1피연산자] | [제2피연산자] |
사용 예 | TEST | AL | 00001001b |
AL 레지스터에 비트 0과 비트 3이 둘아 0인지 확인하고 싶다면, 제2피연산자에 비트 0(오른쪽의 첫 번째 비트)과 비트 3(오른쪽에서 네 번째 비트)에 1을 적고 나머지에는 0을 적은 후 TEST 명령을 실행한다. AL의 비트 0과 비트 3이 모두 0이라면 ZF가 세트된다. 비트 0과 비트 3 중 하나라도 1이면 ZF는 클리어된다. AX가 0x08h라면 비트 3이 1이므로 ZF는 클리어된다. |
기타 논리 명령
-
AND, OR, XOR, NOT, TEST 외 기타 논리 명령은 다음과 같다.
명령 | 설명 | |
SHL / SAL | Shift Left / Shift Arithmetic Left | 왼쪽으로 피연산자만큼 자리옮김(이동) |
SHR / SAR | Shift Right / Shift Arithmetic Right | 오른쪽으로 피연산자만큼 자리옮김(이동) |
ROL | Rotate Left | 왼쪽으로 피연산자만큼 회전 이동 |
ROR | Rotate Right | 오른쪽으로 피연산자만큼 회전 이동 |
RCL | Rotate through Carry Left | 자리 올림(Carry)을 포함 왼쪽으로 피연산자만큼 회전 이동 |
RCP | Rotate through Carry Right | 자리 올림(Carry)을 포함 오른쪽으로 피연산자만큼 회전 이동 |
1-4. 스트링 명령
-
바이트로 구성된 데이터를 메모리에서 가져오거나 메모리로 전송
REP (Repeat)
-
ADD나 MOVS 같은 작동 코드 앞에 위치
-
CX가 0이 될 때까지 뒤에 오는 스트링 명령을 반복
형식 | REP | 작동 코드 | - |
MOVS (Move String)
-
바이트나 워드, 더블 워드를 옮기는 명령으로 각각 MOVSB, MOVSW, MOVSD가 있음
-
DS:SI가 지시한 메모리 데이터를 ES:DI가 지시한 메모리로 전송
-
MOVS는 피연산자 없이 단독으로 쓰며, 다음 REP 등과 함께 사용되기도 함
형식 | MOVSB | ||
사용 예 | CLD LEA SI, String_1 LEA DI, String_2 MOV CX, 384 REP MOVSB |
||
CLD (Clear Direction) : 디렉션 플래그를 지움 LEA SI, String_1 : String 1의 주소 값을 SI (Source Index)에 저장 LEA DI, String_2 : String 2의 주소 값을 DI (Destination Index)에 저장 MOV CX, 384 : CX에 384를 저장 REP MOVSB : SI에서 DI까지 CX가 0이 될 때까지 1바이트씩 복사 |
기타 스트링 명령
-
REP, MOVS 외 기타 스트링 명령은 다음과 같다.
명령 | 설명 | |
CMPS | CoMPare String | DS:SI와 ES:DI 내용을 비교한 결과에 따라 플래그 설정 |
SCAS | SCAn String | AL 또는 AX와 ES:DI가 지시한 메모리 내용을 비교한 결과에 따라 플래그 설정 |
LODS | LOaD String | SI 내용을 AL 또는 AX로 로드 |
STOS | STOre String | AL 또는 AX를 ES:DI가 지시하는 메모리에 저장 |
1-5. 제어 전송 명령
-
점프 (분기), 조건 점프 (조건 분기), 루프, 호출과 리턴 연산 등으로 프로그램 흐름 제어
JMP (Unconditional Jump)
-
대표적인 점프 명령
-
프로그램 실행 주소 또는 라벨로 이동
형식 | JMP [제1피연산자] |
사용 예 | JMP 100h |
주소로 직접 지정한 100h번지로 점프 | |
String: MOV CX, 384 | |
... | |
JMP String | |
라벨로 JMP를 지정하는 경우 |
이외에도 JMP 명령은 조건에 따라 다음과 같이 다양하게 사용된다.
명령 | 점프 조건 | 설명 | |
JC | Carry Flag Set | CF = 1 | CF 값이 1이면 점프 |
JNC | Not Carry Flag Set | CF = 0 | CF 값이 0이면 점프 |
JE / JZ | Equal / Zero | ZF = 1 | 결과가 0이면 점프 |
JA / JNBE | above / Not below Not Equal | CF = 0 and ZF = 0 | 결과가 크면 점프 (부호화되지 않은 수) |
JAE / JNB | above Or Equal / Not below | CF = 0 | 결과가 크거나 같으면 점프 (부호화되지 않은 수) |
JB / JNAE | below / Not above Nor below | CF = 1 | 결과가 작으면 점프 (부호화되지 않은 수) |
JL / JNGE | Less / Not Greater Nor Equal | SF != OF | 결과가 작으면 점프 (부호화된 수) |
JBE / JNA | below Or Equal / Not above | (CF or ZF) = 1 | 결과가 작거나 같으면 점프 (부호화되지 않은 수) |
JG / JNLE | Greater / Not Less Nor Equal | ZF = 0 and SF = OF | 결과가 크면 점프 (부호화되지 않은 수) |
JGE / JNL | Greater Or Equal / Not Less | SF = OF | 결과가 크거나 같으면 점프 (부호화된 수) |
JLE / JNG | Less Or Eqal / Not Greater | ZF = 1 or SF != OF | 결과가 작거나 같으면 점프 (부호화되지 않은 수) |
JNE / JNZ | Not Equal / Not Zero | ZF = 0 | 결과가 0이 아니면 점프 |
JNO | Not Overflow | OF = 0 | 오버플로가 아니면 점프 |
JNP / JPO | Not Parity / Parity Odd | PF = 0 | PF가 1이면 점프 |
JNS | Not sign | SF = 0 | SF가 1이면 점프 |
JO | Overflow | OF = 1 | 오버플로 발생 시 점프 |
JP / JPE | Parity / Parity Even | PF = 1 | PF가 1이면 점프 |
JS | Sign | SF = 1 | SF가 1이면 점프 |
JCXZ | CX Zero | CX = 0 | CX가 0이면 점프 |
-
above, below : 부호 없는 두 수의 크기 관계
-
Greater, Less : 부호 있는 두 수의 크기 관계
CALL (Call)
-
JMP처럼 함수 호출 시에 사용하며, 제1피연산자에 라벨 지정
-
하지만 CALL은 리턴 주소로 IP 주소를 백업하여 'PUSH + EIP + JMP'와 의미가 같음
형식 | CALL | [제1피연산자] |
RET (Return from CALL)
-
함수에서 호출한 곳으로 돌아갈 때 사용하는 명령
-
'POP EIP'와 의미가 같음
다음은 CALL과 RET의 예시이며, AX에는 0x08h 값이 저장되었다고 가정한다.
CALL SUBR ADD AX, 10h ... SUBR : INC AX ... RET |
위 에에서는 SUBR 함수를 호출하면, SUBR 라벨이 있는 곳에서 RET까지 실행된다.
이때 INC AX가 있으므로 AX는 0x09h가 된다.
RET 명령이 실행되면 CALL 다음 줄인 'ADD AX, 10h'를 실행한다.
따라서 AX는 0x19h가 될 것이다.
LOOP (Loop CX times)
-
문장들의 블록을 지정된 횟수만큼 반복
-
CX는 자동으로 카운터로 사용하며, 루프를 반복할 때마다 감소
형식 | LOOP | [제1피연산자] |
사용 예 | MOV AX, 0 MOV CX, 5 L1 : INT INT AX LOOP L1 |
|
제1피연산자는 라벨이 되며, 예에서 L1이 CX 숫자만큼 다섯 번 회전하므로 결과적으로 AX는 5가 된다. |
INT (Interupt)
-
인터럽트가 호출되면 CS:IP와 플래그를 스택에 저장하고, 그 인터럽트와 관련한 서브 루틴 실행
-
제1피연산자는 인터럽트의 번지로 00~FF(256개) 번지가 할당되어 있고, INT 10H와 INT 21H 인터럽트 많이 사용
-
INT 10H는 화면 클리어 기능, 커서 위치 설정, 커서 현재 위치 찾기 기능이 있음
-
INT 21H는 모니터에 문자 출력, 키보드에서 문자열 데이터 입력 기능이 있음
형식 | INT | [제1피연산자] |
기타 제어 전송 명령
명령 | 설명 | |
INTO | INTerrupt on Overflow | 오버플로 발생 시 인터럽트 실행 |
IRET | Interrupt RETurn | 인터럽트에서 복귀 (리턴) |
LOOPZ / LOOPE | LOOP while Zero / Equal | 제로 플래그가 1이고 CX 값이 0보다 크면 루프 계속 수행 |
LOOPNZ / LOOPNE |
LOOP while Not Zero / Not Equal |
제로 플래그가 0이고 CX 값이 0보다 크면 루프 계속 수행 |
1-6. 프로세서 제어 명령
-
레지스터의 플래그 값을 세트하거나 클리어
STC (Set Carry)
-
피연산자 없이 사용
-
EFLAGS 레지스터의 CF 값을 세트
NOP (No Operation)
-
아무 의미 없는 명령
-
일종의 빈칸을 채우는 데 사용
기타 프로세서 제어 명령
-
기타 프로세서 제어 명령은 다음과 같다.
명령 | 설명 | |
CLC | CLear Carry | 캐리 플래그 클리어 |
CMC | CoMplement Carry | 캐리 플래그 반전 |
HLT | HaLT | 정지 |
CLD | CLear Direction | 디렉션 플래그 클리어 |
CLI | CLear Interrupt | 인터럽트 플래그 클리어 |
STD | SeT Direction | 디렉션 플래그 세트 |
STI | SeT Interrupt | 인터럽트 인에이블 플래그를 세트 |
WAIT | WAIT | 프로세스 일시 정지 상태 |
ESC | ESCape to External Device | 종료 명령 |
# Reference
https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872
'System' 카테고리의 다른 글
[System] 어셈블리어 구조 & 주소 (0) | 2020.03.20 |
---|---|
[System] 80x86 시스템 메모리 구조와 동작 (0) | 2020.03.18 |
[System] 80x86 시스템 CPU 구조와 레지스터 (0) | 2020.03.17 |
[System] 운영체제 이해 (0) | 2020.01.14 |