크리에이티브 커먼즈 라이센스

홈페이지HOME

PHP

JavaScript

HTML

CSS

드롭다운메뉴

제로보드4

도   움   말

백지 건강강좌/자가임상체험

물박사(자가면역질환...)^미러

전동명(천연물질사전)^미러

竹田 장승옥(블로그)^글목록

계산환산(계산기)^ 단위변환

관주성경 TTS 일반파일 TTS

바이블로 Bible_ro 다운로드

다운로드>폰에 복사
>파일선택...설치됩니다.

[도움말 보기] 바로가기

개선 요구, 충고는
아래 관리자 연락
전화/메일 부탁 드립니다.
최대한 빨리 처리하고
업데이트 올리겠습니다.

이 글은 1994. 8.월초(?)경부터 하이텔에 올렸던 자료이다.

하이텔에 들어가 보니 일부 없어진 것이 있는데, 다행히 내 컴퓨터에서 찾았다.

asm_03. (인터럽트)

프로그래밍 언어도 하나의 언어입니다.

언어란 하나의 약속입니다.

우리가 약속을 모를 때 우리는 전혀 무능한 사람입니다.

그러나 일단 약속을 알고 나면 우리는 유능한 사람이 됩니다.

우리는 외국 사람들과 대화하기 위하여, 그 외국 사람들 사이의 약속인 해당 외국어를 열심히 배웁니다.

프로그래밍 언어를 배우는 것은 확실히 그보다 쉽습니다.

제 03 장  인터럽트

우리는 머리도 식힐 겸 add, sub, mul, div라는 사치연산 명령을 배웠다.

이제 우리는 상당히 유용하고 강력한 인터럽트 명령을 알아 보자.

흔히 인터럽트라는 말은 많이 들었어도, 정확한 뜻은 잘 모를 것이다.

그러나 이미 우리는 디버그 입문에서 인터럽트를 사용해 보았다.

한 문자를 출력하는 프로그램을 간단하게 만들어 본 기억이 날 것이다.

그 프로그램은 인터럽트를 이용한 것이었다.

이제 다시 비슷한 프로그램을 하나 만들면서, 이론적으로 정리하기로 하자.

    ## 필자통신

이번 장부터는 이전 장의 복습을 생략한다.  그러나, 어떤 내용을 배운 직후에 다음 내용을 배우기 전에 한두 번 이상의 복습을 해 두는 것이야말로 학습의 능률을 최대한으로 거두는 비결임을 잊지 말기 바란다.

필자가 시간에 쫓겨 생략하더라도, 방법을 알기 때문에 각자 복습하기를 포기하지 않을 줄 믿는다.

제 1 절  문자 출력 맛보기

인터럽트(interrupt)를 사용하는 명령어는 int이다.

int 명령어를 이용하여 가볍게 한 문자를 화면에 출력해 보자.

제 00 장(디버그 입문)에서 만들어 본 프로그램이므로, 쉬울 것이다.

이 장에서는 복습을 겸해서 이론적인 면을 정리해 둠으로써 앞으로의 프로그래밍 실습의 탄탄한 기초를 다지기로 하자.

1.  입출력 함수 INT 21h

int 명령어 중에서도 화면에 문자를 출력하거나 키보드로 부터 입력을 받아 들이는 등 입출력 작업을 디버그에게 지시하는 명령은 int 21h이다.

사실은 디버그가 도스에 내장된 int 21h 함수를 호출 사용하는 것이다.

int 명령어의 기계어 코드는 CDh이다.

그렇다면 우리가 int 21 명령을 사용하기 위해 어떤 기계어 코드를 입력할까?

앞서 8088의 덧셈이라는 제목 이후에서 자세히 설명한 것을 기억해 보자.

오프셋 메모리 100h로부터 시작하여 cd, 21을 차례로 입력(Enter)하면 된다.

     - debug

     - e 100

     ????:0100 ??. cd   ??. 21

     -

화면에 ? 표시는 그 자리에 어떤 숫자가 나타나도 무방하다는 뜻이다.

이렇게 표시하는 것이 보기도 쉽고, 빠른 이해를 도울 것이라고 믿기 때문에 앞으로 가능하면 신경쓸 필요가 없는 부분에는 ? 표시를 많이 쓰겠다.

이제 r 명령을 해 보면, 보고서 셋째 줄이 다음과 같이 보일 것이다.

    ????:0100 cd21         int     21

2.  출력 명령 AH=02

int 21h 함수에는 여러 개의 명령들이 포함되어 있다.

우리가 int 21h 함수를 호출했을 때, 그 함수는 ah(ax 레지스터의 상위 바이트)에 어떤 값이 저장되어 있는지를 참조하여 실제 어떤 작업을 한다.

ah 레지스터의 값이 02라면, 화면에 어떤 문자를 출력하게 된다.

3.  상위, 하위 바이트

지금까지 보지 못한 ah 레지스터라는 말이 나왔으니 설명이 필요할 것이다.

사실은 별도의 레지스터가 있는 것은 아니다.

8088의 13 개 레지스터는 모두 워드(2 바이트) 길이라는 사실은 이미 알았다.

따라서, 하나의 레지스터를 절반으로 나누면 각 1 바이트 길이로 나뉜다.

그 둘 중 상위 바이트는 ?h, 하위 바이트는 ?L로 표시하는 것이다.

4.  AX=0200

int 21h 함수로 하여금 문자를 출력하도록 만들기 위하여 ah 값을 02로 만들자.

그런데, 아직 상위나 하위 각 바이트 값을 다루는 일은 배우지 않았다.

물론 사용은 해 보았지만, 기억하기도 어려울 것이다.

우선 ax 값을 0200으로 만들면, 상위 바이트 ah 값은 02가 될 것이다.

     - r ax

     ax ????

     : 200   * ah 레지스터에 출력명령 코드값 02h를 저장 *

     -

0200을 입력할 필요는 없다.  200만 입력하면 그만이다.

이제 int 21h 함수를 호출하여, 문자를 출력하는 명령은 완성되었다.

5.  출력할 문자

이제 어떤 문자를 화면에 출력할 것인지를 결정해 주어야 된다.

가령 A라는 문자를 출력하려면 어떻게 해야 될까?

우리가 디버그에게 A라는 문자를 가르쳐 주어도 디버그는 알지 못한다.

그 대신 아스키(Ascii) 문자 A를 표시하는 16진수(hex) 코드 값을 입력해야 되는데, 그 코드 값은 41h이다.

아스키 문자 256 개의 코드값은 어셈블리 참고서 등의 부록에 나와 있다.

따라서 디버그로 하여금 문자 A를 화면에 출력하라고 명령하기 위해 우리는 그 문자의 코드값을 디버그에게 전해 주어야 된다.

6.  출력할 문자를 저장하는 레지스터 DL

문제는 디버그가 그 값이 어디에 있는지를 알아야 그 값에 해당되는 아스키 문자를 화면에 출력해 줄 것이 아닌가?

즉 우리가 출력하기 원하는 아스키 문자의 코드값을 어느 레지스터를 통하여 디버그에게 전해 주어야 하는지 알아야 될 것이다.

디버그는 int 21h 함수 중 출력 명령(ah=02)을 받으면 dl 레지스터에 저장된 크드값에 해당되는 아스키 문자를 화면에 출력해 준다.

따라서 우리는 A의 코드값 41h를 dl 레지스터에 저장해 주면 될 것이다.

7.  DX=0041

출력할 문자를 A로 지정하기 위해 dl 값을 41로 만들자.

우선 dx 값을 0041으로 만들면, 하위 바이트 dl 값은 41이 될 것이다.

     - r dx

     dx ????

     : 41

     -

8.  문자 출력

이제 모든 준비가 끝났다.

실행을 해 보자.

     - r     * 각 레지스터의 값, 실행할 명령 등이 정확한지 확인 *

     (생략)

     - r ip * ip 레지스터가 0100이 아닌 경우 *

     ip ????

     : 100   * 그 값(ip 값)을 0100으로 지정 *

     - g 102         * 오프셋 100h, 101h에 있는 int 21 명령만 실행 *

숙달된 후라면 모르겠지만, 초보자 시절에는 사소한 입력 실수를 하기 쉽다.

또한 의외로 사소한 실수를 발견하지 못하여 헤메는 일도 많은 법이다.

"int 20"이라는 명령은 정확하게 입력되어 있는가?

두 레지스터 ax, dx에 넣어 준 16진수 값은 정확한가?

그 모든 것을 r 명령 하나로 확인할 수 있다.

특히 중요한 것은 ip 레지스터 값이 0100으로 맞춰져 있어야 된다는 점이다.

그 값이 틀리면 엉뚱한 명령이 보일 수 밖에 없으며, 실행해서는 안 된다.

g <번지> 명령은 디버그로 하여금 지정한 번지 바로 앞까지의 메모리에 저장된 명령만 실행하고 실행을 중단하라고 지시하는 뜻의 go till 명령어이다.

정확하게 진행했다면 위에 이어지는 화면은 다음과 같이 보일 것이다.

     A

     AX=????

                   IP=0102

     ????:0102 ????         ???     ??,??

     -

첫줄에 우리가 원한 A를 출력하고, 그 아래 세 줄에 걸쳐 레지스터의 상태를 보여 주는데, 앞에서 본 바와 마찬가지로 ip 레지스터 값은 102h로 변해 있다.

하나의 명령어를 실행한 후에는 그 다음 번지를 가리키기 때문이다.

제 2 절  인터럽트 함수

간단한 한 문자를 출력하기 위하여 위와 같이 복잡한 작업을 해야 되다니...

누구나 비슷하겠지만, 필자도 그런 일은 딱 질색이다.

그러나, 방법이 그것 뿐이라면 어떻게 하겠는가?

나아가, 하나를 표시할 수 있다면 아무리 많은 것도 표시할 수 있다.

기본적인 방법을 확실하게 알면 만사형통(?)이다.

기대를 가지고 좀 더 열심히 노력하자.

인터럽트에 관하여 약간의 이론 정리를 하고 넘어가자.

나중에는 보약이 될 터이니까.

1.  인터럽트 함수의 종류

인터럽트란 문자 그대로 무언가를 가로챈다는 말이다.

무언가가 있어야 그 무언가를 가로챌 수 있을 것이다.

그 무언가를 신호라고 생각하자.

사실 사람과 사람이 뜻을 통하는 말이나 글도 모두 신호의 일종이다.

사람과 컴퓨터도 각종 신호로 뜻을 주고 받는 것이 아닌가?

인터럽트 함수에는 int 10h, 16h, 20h, 21h, 25h, 26h 등이 있다.

그 중 int 25h, int 26h 함수의 용도는 다음과 같다.

    int 25h 함수 : 디스크의 특정 섹터를 메모리로 읽어 들임

    int 26h 함수 : 메모리의 내용을 디스크상의 특정 섹터에 기록

그 명령에 필요한 파라미터 등은 나중에 보기로 하자.

특별히 int 20h 함수는 파라미터 없이 사용되며, 지금(바로 앞 번지의 메모리에 저장된 명령)까지 실행되던 프로그램을 종료하는 역할을 한다.

디버그(도스)상에서 어떤 프로그램이 int 20h 함수를 만나면 실행을 끝내고 모든 제어권을 디버그(도스)에게 되돌려 주게 된다.

int 20h 함수에 대해서는 다음 항목에서 기능 실습을 보충하기로 한다.

나머지 int 10h, 16h, 21h 함수는 여러 가지 명령을 포함하고 있다.

각 인터럽트 함수의 구체적인 사용법은 차차 공부하기로 하자.

이 정도로 인터럽트 전반의 윤곽 보기를 마치기로 한다.

2.  프로그램을 끝내 주는 int 20h 함수

가장 간단한 int 20h 함수의 사용법을 실습해 보자.

그 이전에, 우리가 어떤 프로그램을 실행할 때 오프셋 번지에 들어 있는 명령부터 실행되기 시작한다는 사실을 기억하자.

그리고 오프셋 번지는 ip 레지스터에 저장된 값으로 표시되었다.

int 20h 함수는 단지 프로그램을 끝낼 뿐, 다른 어떤 값을 찾아 참조하지도 않으며 다른 어떤 값을 변화시키지도 않는다.

따라서 단지 어떤 메모리 오프셋 번지에 int 20h 명령을 저장해 두고, ip 레지스터의 값을 그 명령 시작 번지에 맞추어 두기만 하면 준비는 끝난다.

지금까지 착실히 두드려 보았다면 긴 설명이 필요 없을 것이다.

알(r) 리(e)가 있을까? 한 말을 기억할 것이다.

메모리 편집을 하려면 e 명령을 사용하며, 기계어 코드를 직접 입력해야 된다.

여기서는 int 명령어의 기계어 코드가 cd였다는 사실만 기억하면 된다.

     - e 102

     ????:0102 ??. cd   ??. 20

     -

먼저 메모리 102번지를 편집하기로 하고 int 20h 명령을 메모리에 입력(편집)하기 위해 cd와 20을 차례로 입력했다.

중간의 스페이스바를 누른 것은 엔터를 하면 편집이 끝나기 때문이며, 이어지는 번지에 다른 내용을 계속 입력할 때는 스페이스바를 누르면 된다.

     - r ip

     ip ????

     : 102

     -

디버그 안에서 어떤 프로그램을 실행하기 전에는, 언제든지 먼저 ip 레지스터값을 확인하여 실행을 시작할 오프셋 번지를 맞추어 두어야 된다.

숙달된 후에도 마찬가지이지만, 처음 배울 때부터 정확하게 기초를 다져 나가는 일은 매우 중요한 것이며 빠른 발전을 보장해 줄 것이다.

     - g


     Program terminated normally

     -

이제 g 명령을 내리면 앞서 지정해 준 ip 번지 즉 오프셋 102h 번지에 입력해 두었던 내용인 int(인터럽트)의 기계어 cd 명령부터 실행된다.

그 번지의 내용 하나만으로 뜻이 통하지 않으면, 그 뒤의 번지에 차례대로 이어지는 내용을 연결하여 하나의 완전한 명령이 되는 번지까지의 내용을 하나로 묶어 실행하게 된다.

이어지는 내용 20까지 붙이면 int(cd) 20으로 하나의 완전한 명령이 된다.

그리고 나서 디버그는 그 뒤의 번지로부터 또 연결되는 하나의 다른 명령을 수행하는 식으로 계속될 것이다.

그런데 위의 화면을 보면 아무 한 일도 없이 단지 프로그램이 정상적으로 끝났다는 메시지만 보여 주고 끝났다.

이것으로 int 20h 함수가 프로그램을 끝내는 역할을 한다는 증명이 되었다.

처음 명령 하나로 프로그램을 끝내었기 때문에, 다른 일을 할 이유가 없다.

이제 레지스터 상황이 어떻게 되어 있는지 확인해 보자.

알 리가 있을까?

레지스터 상황을 보는 디버그 명령은 알(r)이었다.

     - r


               IP=0102

     ????:0102 CD20         INT     20

     -

종합적으로 다시 정리해 보자.

앞절에서는 100h 오프셋에 int 21h 즉 문자 입출력 함수를 입력하고, ah와 dl 레지스터에 문자 출력 명령 및 출력할 문자의 코드값을 저장한 후 g 102 명령으로 메모리 100h, 101h의 int 21 명령 수행 후 프로그램을 끝내도록 하였다.

물론 그 실행 당시 ip 레지스터 값은 0100으로 맞추어 두었다.

그와 달리, 이번에는 102h 오프셋에 int 20h 즉 프로그램을 끝내는 함수를 입력하고, 단지 g 명령만 주었다.  ip 레지스터는 0102로 맞추어 두고...

그러자 "Program terminated normally"라는 메시지가 나왔다.

이것으로 int 20h 함수가 프로그램을 끝내는 역할을 한다는 증명이 되었다.

3.  명령어의 결합

이미 우리는 오프셋 100h, 101h에 int 21h 함수를 입력하고 ah, dl 레지스터 각각에 출력 명령 및 출력할 문자 A의 코드값을 저장해 두었다.

그것을 변경시키지 않기 위해, 마지막으로 오프셋 102h, 103h에 프로그램을 끝내 주는 int 20h 함수를 입력했으며, 그 명령을 실행해 보기도 하였다.

이제 ip 레지스터를 100h로 되돌려 두고 g 명령으로 실행해 보자.

     - r ip

     ip 0102

     : 100

     - g

     A

     Program terminated normally

     -

어떤가?

프로그램은 100h, 101h에서 int 21h 명령을 받고 ah 레지스터 값 02h를 참조하여 dl 레지스터의 코드값 41h에 해당되는 문자 A를 출력해 주었다.

그리고 102h, 103h로 넘어가 int 20h 명령을 받고 프로그램을 끝내 주었다.

이런 식으로 짜 맞추다 보면, 쓸만한 프로그램도 만들 수 있게 된다.

지루하게 생각할 것이 아니라, 하나씩 확실하게 이해하고 넘어가야 된다.

별 재미도 없는 기초적인 지식이 실제로는 대단히 중요한 것이다.

    ## 발전 참고

지금 우리는 매우 느린 걸음으로 걷고 있다.  우리는 이미 수작업으로 ax 레지스터에 0200을 입력하고, 또 dx 레지스터에 0041을 입력해 두었으며, 그 레지스터의 값이 변경되지 않았기 때문에 int 21h 명령만으로 아스키 문자 A를 출력할 수 있었다.  그러나 만약 중간에 다른 작업을 하거나 다른 프로그램을 실행하여 그 두 레지스터의 값이 변경된 후였다면 우리가 원하지 않은 엉뚱한 결과를 보게 되었을 것이다.

다른 프로그램의 실행에 영향을 받지 않고 원하는 결과를 얻기 위해서는 int 21h 명령 이전에 그 두 레지스터 값을 입력해 주어야 된다.

또한 우리가 이 프로그램에서 변경한 그 두 레지스터 값을 메모리에 그대로 남겨 둠으로써 다른 프로그램의 실행에 영향을 주는 일을 피하려면 먼저 그 두 레지스터에 있던 기존의 값을 스택이라는 메모리 구역에 저장해 두었다가 복구하는 기술이 필요하게 된다.

말만 들으며 어렵게 느껴질 수도 있지만, 실제로 해 보면 아주 쉽다.

다음 장 이후에 그런 내용을 쉽게 구체적으로 배우게 될 것이다.

ID:
PW:

     0 분
     8 분

자유게시판

건강백과 HOME

홈페이지 HOME

조   약     HOME

생활지혜 HOME

서식양식 HOME

법원 전산양식 검색

In Na zum

비공개 HOME

백과넷 포탈 : 건강/법률(메인)/홈피/서식/조약/생활지혜

◁ 2002.9.1.~2021.4.11. ▷

관리자 연락(저작권 의심 신고) : 김병희 010-6204-4973 k8z7@hanmail.net