태초의 프로그래밍 언어 어셈블리

assembly, 8086, x86

바이오스가 제공하는 인터럽트

호랑이 담배피던 시절 이야기를 하겠습니다. 그냥 재미로 봐주세요. 요즘 환경과는 별로 관련이 없습니다.

옛날 옛적에 바이오스라는게 있었습니다. 지금도 있지만 옛날에는 조금 달랐습니다. 지금은 윈도우를 부팅시켜주는 역할이 대부분이지요. 사실은 그보다 더 복잡하지만 99%의 사용자와 99%의 개발자들은 그 이상 알 필요가 없습니다. 그런데 옛날 옛적 도스 시절에는 바이오스란 개발에 없어서는 안될 중요한 자원이었습니다. 바이오스가 제공하는 함수들이 바로 인터럽트입니다.

원래 인터럽트는 그게 아닌데? 생각하시는 분들이 많으실겁니다. 맞습니다. 원래 인터럽트란 외부 장치로부터 들어오는 신호가 인터럽트이지요. 정확히 말하면 바이오스가 제공하는 예외처리나 소프트웨어 인터럽트라고 하는게 맞습니다. 하지만 프로세서 명령어의 이름이 인터럽트라서 인터럽트라고 보통 부릅니다.

중요한건 이름이 뭐냐가 아니라 무슨 일을 하느냐겠지요. 바이오스가 제공하는 기능이 뭐냐가 중요한건데 주로 장치들을 제어하는 기능을 제공합니다. 모니터에 글자를 출력하는 인터럽트가 있습니다. 이전에 함수 만들기 예제에서 int라는 명령어가 있었습니다. 그게 인터럽트 명령어입니다. 모니터 (정확히는 비디오 출력)을 제어하는 것입니다.

또 옛날 컴퓨터에 어떤 장치들이 있었는지 생각해보세요. 모르시는 분들이 많으시겠지만 플로피 디스크라는게 있었고, 또 그 옛날에도 부자들은 하드디스크를 썼었습니다. 전화선을 꼽아서 쓰는 모뎀이라는게 있어서 하이텔에 접속해서 동호회활동도 했었지요. 테이프를 써서 음악을 듣는게 아니라 게임을 하기도 했습니다.

이런 장치들을 프로그래밍하는데 바이오스의 인터럽트를 사용하는 것입니다. 왜 그랬냐면 컴퓨터라는게 IBM-compatible이라는 일정한 규칙대로 만들어지기 때문입니다. 자세한건 저도 모릅니다. 스펙 문서는 따분하고 어렵습니다. 그냥 컴퓨터를 만들기 위한 규칙이 있는데 그런 규칙에 따라 이런 장치는 이렇게 조정해야한다라는 세부 규칙이 있습니다. 그런 규칙을 프로그래머가 일일이 프로그래밍해야되면 너무 복잡하니까 바이오스 회사에서 라이브러리처럼 제공해주는 것입니다.

요즘은 운영체제가 그런 일을 합니다. 리눅스 커널을 보면 모든 장치들을 제어하기 위한 프로그램들이 들어있어서 바이오스는 리눅스 커널이 부팅된 이후부터는 아무런 일도 안해도 됩니다. 저는 컴퓨터가 부팅된 다음에 바이오스에 연결된 동그란 건전지를 빼서 바이오스를 정지시켜봤습니다만 컴퓨터는 계속 잘 동작했습니다.

옛날옛날에는 그런 운영체제가 없었습니다. 도스가 있었다고요? 도스는 운영체제가 아닙니다. 그냥 쉘이라고 부르는게 더 정확합니다. 높은 버전의 도스는 스케줄링도 한다고 들은것 같은데 원래의 도스는 그냥 사용자가 입력한 프로그램을 실행시켜주는 실행시나 쉘 정도였습니다. 어쨌든 그래서 바이오스의 인터럽트를 많이 사용했었습니다.

역사 이야기는 그만하고 다시 인터럽트로 돌아갑시다. 예를 들어 문자를 화면에 출력하기 위해서는 화면의 몇번째 줄 몇번째 칸에 글자를 출력해야할지 프로그램에서 관리를 해야했습니다. 하지만 인터럽트를 이용하면 그런 위치에 신경쓸 필요없이 문자를 출력할 수 있고, 한 화면을 다쓰면 알아서 스크롤도 해줍니다. 스크롤하는 코드도 은근히 긴데 이렇게 라이브러리처럼 만들어줬으니까 편리합니다.

인터럽트를 실행하는 명령어는 int 입니다. 그리고 인터럽트의 번호를 쓰면 됩니다.

int 10h

인터럽트 번호는 0부터 255까지입니다. 그렇다고 인터럽트가 256개인것은 아닙니다. 인터럽트 번호와는 따로 sub 번호라는게 있어서 인터럽트를 호출할 때 ah 레지스터에 sub 번호를 지정합니다. 그래서 총 256*256 개의 인터럽트가 존재합니다.

다음 예제는 화면에 Hello를 출력하는 예제입니다.

ORG    100h ; directive to make a simple .com file.

; The sub-function that we are using
; does not modify the AH register on
; return, so we may set it only once.

MOV    AH, 0Eh    ; select sub-function.

; INT 10h / 0Eh sub-function
; receives an ASCII code of the
; character that will be printed
; in AL register.

MOV    AL, 'H'    ; ASCII code: 72
INT    10h        ; print it!

MOV    AL, 'e'    ; ASCII code: 101
INT    10h        ; print it!

MOV    AL, 'l'    ; ASCII code: 108
INT    10h        ; print it!

MOV    AL, 'l'    ; ASCII code: 108
INT    10h        ; print it!

MOV    AL, 'o'    ; ASCII code: 111
INT    10h        ; print it!

MOV    AL, '!'    ; ASCII code: 33
INT    10h        ; print it!

RET               ; returns to operating system.

인터럽트 번호는 10h이고 서브번호는 0eh입니다. 인터럽트마다 필요한 데이터를 전달하는 방식이 다른데 int 10h는 al에 출력할 글자를 저장해서 전달합니다.

http://gurugio.kldp.net/wiki/wiki.php/emu8086/%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8%EB%A6%AC%EC%8A%A4%ED%8A%B8

그 외에 어떤 인터럽트들이 있는지는 제 홈페이지 링크를 참고하시기 바랍니다. 별별 기능들이 다 있습니다.

인터럽트의 호출

인터럽트를 호출하는 실행되는 프로그램들은 어디 있는걸까요? 바이오스 칩 안에 있는 메모리에 있습니다. 컴퓨터 슬롯에 끼워쓰는 메모리에 있는게 아닙니다. 단지 메모리에 있는 것처럼 메모리 주소를 가지고는 있습니다.

8086 환경에서는 인터럽트 프로그램의 시작 주소가 0f4000h입니다. 

예를 들면 int 12h는 메모리가 몇 kb인지를 알려주는 인터럽트입니다. 호출하면 ax에 kb 단위로 얼마인지가 저장됩니다. 그리고 이 프로그램은 0f400h:01adh 주소에 있습니다. int 12h를 호출하는대신 call 0f400h:01adh라고 호출해도 환경에따라 될 수도 있습니다. 에물레이터에서는 될지 안될지 모르겠습니다. 한번 해보세요. 실제 컴퓨터에서는 됩니다.

중요한건 어디있냐가 아닙니다. 그냥 int 명령이 어디있는지 찾아서 호출합니다. 우리가 생각해볼건 0f400h:01adh라는 주소에 있는 함수를 호출했다가 복귀하기 위해서는 일반적인 함수 호출과는 다른게 필요하다라는 것입니다.

일반적인 함수 호출은 call 1234h이고 스택에 복귀 주소 10bh가 저장됩니다. 그런데 여기에 생략된게 있습니다. 실행되는 코드의 주소는 원래 cs:ip로 표시됩니다. 데이터가 ds:bx로 표시되는 것과 마찬가지입니다. 모든 주소는 세그먼트 레지스터와 일반 레지스터로 표시하게 되있습니다.

그럼 인터럽트 함수의 주소는 f400h:1adh이고 복귀해야할 주소는 700h:10b입니다. 세그먼트 주소가 다릅니다. 인터럽트가 실행될때 cs는 f400h이고 ip는 1adh일텐데 스택에 복귀주소가 10b가 저장되어있으면 f400h:10bh로 복귀해서 제대로 복귀되지 않고 또다시 어떤 인터럽트의 코드가 실행됩니다.

따라서 인터럽트를 호출할 때는 세그먼트의 주소도 스택에 저장해서 복귀할 때 세그먼트 주소와 ip 주소가 모두 되돌려져야합니다. 이런걸 far call 이라고 합니다. 단순히 16비트의 ip 주소만 바꾸는게 아니라 더~~ 멀리 가도록 한다는 것입니다.

int 명령을 실행한 후에 스택에 저장된 값들을 확인해보세요.

다시한번 말씀드리지만 인터럽트의 내용들은 운영체제를 만들거나하지 않는 이상 별로 필요없는 내용입니다. 그냥 컴퓨터의 내부 원리를 알고싶으신 분들은 재미로 보셔도 좋습니다. 어쨌든 far call이라는게 있다는건 좀 흥미롭긴 합니다.

댓글

댓글 본문
작성자
비밀번호
버전 관리
gurugio
현재 버전
선택 버전
graphittie 자세히 보기