• Code Segment만 존재하는 예

  • CODE SEGMENT로 시작 ASSUME으로 이름을 지정
  • MOV로 AH, AL레지스터에 값을 대입 -> AX = 1234H
  • ADD로 AH + AL 후 결과 값을 AH에 저장
  • 프로그램을 종료할 때 빨간 네모 안의 명령을 실행 -> 인터럽트 호출(시스템 콜) - 트랩
  • 데이터 정의 의사 명령어

  • 데이터를 정의하기 위해 지시자가 필요
  • Byte단위, word단위 등 단위가 정해져 있음
  • 8086은 16bit이므로 DW를 사용
  • 하나를 써도 되고 여러 개를 써도 됨 -> 콤마로 구분
  • 초기값이 없는 경우 0자리에?를 넣으면 자리만 가지고 있고 값은 없음
  • ex) 문자 출력 프로그램

  1. 코드 세그먼트, 데이터 세그먼트가 각각 1개씩 존재
  2. 실행은 별개의 문제이므로 데이터 세그먼트의 주소를 넘겨주기 위해 MOV AX, DATA와 MOV DS, AX를 써준다.
  3. AX를 거치는 이유는 MOV명령에 데이터 이름을 레지스터에 바로 쓰는 경우가 존재하지 않기 때문 -> 범용 레지스터를 거쳐서 저장
  4. INT 21H를 기점으로 나뉜다. -> 4CH는 프로그램을 종료, 2는 문자 하나를 콘솔에 출력하는 시스템 콜
  5. DL에 A를 넣고 출력 -> CX에 4243H를 넣고 CH를 출력(42 - B) -> DL에 CL값(43 - C)을 넣고 출력
  • 주소 지정 방식(Addressing mode)
  • 즉치 주소 지정 방식(Immediate addressing)

ex) MOV AX, 1234H

ex) DAT EQU(define) 1234H

  • 직접 방식(Register addressing; Direct addressing) - 레지스터의 내용을 직접 전송

ex) MOV AH, DH

     MOV DS, AX

ex) MOV AX, DH (X) -> 두 레지스터의 사이즈가 같아야 함

ex) MOV DX, [BX] -> 주소 값을 가져옴

  • 간접 방식(Memory reference addressing; Indirect addressing) - 전송하는 값이 저장되어 있는 번지를 지정(값이 메모리 내에)

ex) MOV AX, DAT -> 변수 이름 = 데이터가 들어가 있는 번지

     MOV AX, [BX+DI+4] -> 번지의 내용(계산) pointer 개념

  1. 없는 경우도 있음 -> 셋 중 하나 이상은 있어야 함
  2. 숫자만 사용할 때 8bit만 가능
  3. [BP + 0]으로만 사용 가능

  1. Data segment는 없지만 Code segment에 데이터가 선언되어있음
  2. 데이터가 있는 경우에는 반드시 MOV AX, CODE와 MOV DS, AX를 사용
  3. MOV BX, OFFSET BUFFER는 BUFFER의 주소 값을 BX에 넣는다는 의미 -> e를 가리킴
  4. BX+SI는 e에서 2칸 옆, 즉 a를 가리킴 -> a를 출력 -> +1 -> m을 출력
  5. CR후 LF는 줄 바꿈
  6. +2를 해서 p가 출력 -> 프로그램 종료

  1. 주소를 나타내는 값을 쓰고자 할 때, 크기를 지정해줌(BYTE, WORD 등)
  • 역 워드 형식 - 순서를 바꿔서 저장

  1. 4243H의 경우 43 42로 저장
  • 덧셈 명령

  • OP1에 OP2를 더해서 OP1에 저장
  • ADC의 경우 Carry Flag도 더해줌

  1. 32비트끼리 연산의 경우 16비트 자리를 각각 정해서 따로 더한 후 합침
  2. 올림이 발생하는 경우에 Carry Flag도 더해줌 -> ADC사용

  1. ADD를 사용하는 BX와 DX는 하위 16비트, ADC를 사용하는 AX, CX는 상위 16비트
  2. 응용

CODE SEGMENT
ASSUME CS:CODE, DS:DATA
	MOV AX, DATA
	MOV DS, AX

	MOV AX, VAR1
	MOV BX, VAR2
	MOV CX, VAR3
	MOV DX, VAR4

	ADD BX, DX
	ADC AX, CX
	MOV VAR1, AX
	MOV VAR2, BX

	MOV AH, 4CH
	INT 21H
CODE ENDS

DATA SEGMENT
	VAR1	DW	1223H
	VAR2	DW	8000H
	VAR3	DW	2000H
	VAR4	DW	8123H
DATA ENDS

END

 

CODE SEGMENT
	ASSUME CS:CODE, DS:DATA
	
	MOV AX, DATA
	MOV DS, AX

	MOV AX, VAR1
	ADD AH, AL

	MOV VAR2, AH

	MOV AH, 4CH
	INT 21H

CODE ENDS

DATA SEGMENT
	VAR1	DW	1234H
	VAR2	DB	?
DATA ENDS

END

CODE SEGMENT
	ASSUME CS:CODE, DS:DATA

	MOV AX, DATA
	MOV DS, AX

	MOV BX, OFFSET VAR1

	MOV AH, [BX]
	MOV AL, [BX+1]

	ADD AH, AL
	MOV VAR2, AH

	MOV AH, 4CH
	INT 21H

CODE ENDS

DATA SEGMENT
	VAR1	DW	1234H
	VAR2	DB	?
DATA ENDS

END

  • 응용 프로그램 - 분기와 반복
  • 증가, 감소 명령

  1. INC에 OP(레지스터나 메모리)를 넣으면 1 증가
  2. DEC에 OP를 넣으면 1 감소
  3. 16비트, 8비트 둘 다 가능
  • 키 입력 방법

  1. 키보드에서 입력받을 수 있음
  2. 에코가 있는 입력은 AH 1번, 없는 입력은 AH 8번 -> 화면에 출력되는지 안되는지의 차이
  3. 키보드로부터 입력을 받을 때까지 기다림 AH로 시스템 콜을 호출하고 입력받은 값을 AL에 저장
  4. 입력받은 값들을 차례대로 출력
  • 비교 명령어

  1. 비교하여 같으면 플레그를 1로 만들고 다르면 0으로 만듦
  2. 플레그 값에 따라 명령을 달리 수행

  1. 두 값의 AND연산 결과에 따라서 플레그를 달리해줌
  2. CL이나 ZF의 값이 변하면서 플레그가 달라짐
  • 분기 명령어의 비교

  1. AX와 0을 비교
  2. 같으면 JE를 0으로
  3. 플레그의 값에 따라 점프하는 라인이 달라짐

  1. 값을 입력 받음
  2. DL에 저장
  3. DL값을 1 증가시킨 후 출력
  4. JMP로 다시 처음으로 돌아감 -> 무조건 분기(무한루프)

  1. AX = 0, CX = 1
  2. AX + CX = 1
  3. CX += 1
  4. CX와 10 비교
  5. JBE -> 작거나 같으면
  6. SUM10으로 돌아감
  7. 11이 되는 순간 JBE를 안 거치고 다음으로 넘어감 -> 10번 반복
  8. 1~10까지 AX에 더한 것을 TOTAL에 저장

  1. A : 크다
  2. B : 작다
  3. E : 같다
  4. N : 아니다
  5. A> B이면 JA -> CMP A, B 후에 JA를 쓰면 A가 큰 경우의 조건문 => JNBE는 작거나 같지 않다(크다)
  6. A>=B이면 JNB(작지 않다), JAE(크거나 같다)

  1. 플레그 레지스터를 이용한 분기
  2. 한 번 읽어볼 것

  1. 에코 있는 입력을 받음, AL에 저장
  2. 20H(스페이스)와 비교
  3. 같으면 EXIT로 점프 -> 프로그램 종료
  4. 아니면 'A'와 비교
  5. 'A'보다 작으면 PRINT로 점프 -> 입력받은 값을 출력 -> NEXT로 돌아가서 다시 입력 받음
  6. 아니면 'Z'와 비교
  7. 'Z'보다 크면 PRINT
  8. 위의 조건들을 살펴보았을 때, 스페이스를 입력받으면 프로그램 종료, A보다 작으면 출력, Z보다 크면 출력이므로 대문자 A~Z까지의 문자만 조건문에 걸리지 않고 넘어갈 수 있음
  9. 대문자인 경우 AL에 'a' - 'A'(대소문자 차이)를 더해줌 -> 대문자를 소문자로 바꿔줌
  10. 소문자를 출력
  11. 대문자를 소문자로 바꾸는 경우도 생각해보자
  • 예제

CODE SEGMENT
	ASSUME CS:CODE
	MOV CX, 10

LOOP1:	MOV AH, 8
	INT 21H

	CMP AL, 20H
	JE EXIT

	CMP AL, 'a'
	JB PRINTZ

	CMP AL, 'z'
	JA PRINTZ

	MOV DL, AL
	MOV AH, 2
	INT 21H

	LOOP LOOP1

EXIT:	MOV AH, 4CH
	INT 21H

PRINTZ:	MOV DL, '0'
	MOV AH, 2
	INT 21H
	DEC CX
	CMP CX, 0
	JE EXIT
	JMP LOOP1

CODE ENDS
END
  • 반복 명령어

  1. LOOP는 CX의 값을 필수로 사용 -> 카운터의 기능
  2. CX의 값만큼 반복 -> 1씩 줄여가며 반복
  3. 중간에 CX값을 바꿔버리면 횟수가 바뀌어 무한루프가 발생할 수 있음

  1. 참고만 할 것 -> 너무 깊다!
  • 응용 코드 작성

  1. 모델 스몰 부분은 그대로 써줌
  2. 스택 - 시작 부분
  3. 데이터 - 데이터 세그먼트 대신에 써줌 - 더 간편하게 사용 가능
  4. @data : get data segment -> 반드시 써야 하는 부분, 세그먼트 이름 대신에 써야하는 것
  5. 나머지 부분은 포맷, 똑같이 써도 되고 이전에 배운 것들처럼 써도 됨
  6. int 21h의 9번 기능 -> 2번은 문자 하나, 9번은 문자열을 출력
  7. 문자가 끝나는 부분은 $로 끝을 냄 -> 처음부터 $전까지 출력
  8. dx에 prompt의 시작 주소를 넣어줌 -> 시작 주소의 문자열을 출력($까지)
  9. 21번 -> 에코 있는 입력
  10. 입력받은 값에서 20h를 빼고 char에 저장
  11. msg의 시작 주소를 dx에 넣고 출력 -> 0Dh.0Ah. 는 줄 바꿈
  12. 9번은 시작 주소로부터 $까지 출력하는 함수
  13. 실행 예

  • 도스 command line에서의 실행 예

  • 스택의 동작

  • 16bit 컴퓨터이므로 push와 pop은 2byte씩 이루어짐
  • push로 OP의 값을 stack에 저장, pop으로 stack의 데이터를 OP에 저장

  1. AX, BX PUSH
  2. PUSHF는 플레그를 PUSH 한다는 의미
  3. POP은 OP를 꺼낸다는 뜻이 아니고 정해진 순서대로 꺼내서 OP에 저장한다는 의미
  • 서브루틴 사용법

  • 서브루틴은 C언어에서 위치를 호출하는 것
  • CALL은 되돌아올 주소를 자동으로 stack에 저장한 후 lable로 점프 -> 진행하다가 return을 만나면 저장해 두었던 주소를 pop 하여 되돌아감

  1. 레이블을 콜 하여 점프 후 RET를 만나면 다시 돌아감

  • 잘 읽어보고 만들어볼 것
  • 정답

  • 코드를 이해하여 앞과 비교해보고 직접 작성도 해볼 것
  • AND와 SHIFT를 사용한 코드
CODE SEGMENT
	ASSUME CS:CODE, DS:DATA

	MOV AX, DATA
	MOV DS, AX
	MOV CX, 12

LOOP1:	MOV DX, VAR1
	SHR DX, CL
	AND DX, 000FH

	CMP DL, 0AH
	JAE LEVEL1
	
	ADD DL, '0'
	MOV AH,2
	INT 21H
	
	CMP CL, 0
	JE EXIT

	SUB CL, 4

	JMP LOOP1

LEVEL1:	ADD DL, 'A'-0AH
	MOV AH,2
	INT 21H

	CMP CL, 0
	JE EXIT

	SUB CL, 4

	JMP LOOP1

EXIT:	MOV AH, 4CH
	INT 21H

CODE ENDS

DATA SEGMENT
	VAR1	DW	2B3FH

DATA ENDS

END
  • 10진수 출력
CODE SEGMENT
	ASSUME CS:CODE, DS:DATA

	MOV AX, DATA
	MOV DS, AX

	MOV CX, 0
	MOV AX, 0

	MOV AX, VAR1
	MOV SI, 10

LOOP1:
	MOV DX, 0
	DIV SI
	PUSH DX
	INC CX
	CMP AX, 0
	JNE LOOP1

PRINT:	
	POP DX
	ADD DL, '0'
	MOV AH, 2
	INT 21H
	
	DEC CX
	CMP CX,0
	JNE PRINT

	MOV AH, 4CH
	INT 21H

CODE ENDS

DATA SEGMENT

	VAR1	DW	1234H

DATA ENDS

END
  • PROC에 의한 서브루틴 작성 - 참고

  • System Call의 예

  • 비디오 스테이터스를 돌려줌
  • 설명
  • 입력값을 주면 하는 일, 출력 값

  • 스크롤을 up, down 해주는 시스템 콜

  • prompt를 어디로 옮길 것인지
  • 커서 포지션
  • 예제들 -> 동작시켜볼 것

  • 예제의 내용

  1. 출력한 것을 박스 안에서 스크롤할 수 있음
  2. 출력해놓고 스크롤시키는 프로그램
  3. 응용으로 스크롤 속도를 늦추거나 반대방향으로 스크롤 되게 수정해볼 수 있음 -> 이것도 해볼 것

+ Recent posts