_dos_getvect, _dos_setvect 함수에 관한 질문

freesky의 이미지

C로 인터럽트 처리를 공부하고 있습니다. _dos_getvect()와 _dos_setvect()함수를 사용하고 있는데요.

책에 나와 있는 예제를 한 번 만들어 보았습니다.

Shift+PrtScr 키를 5번 누르면 프로그램이 종료되는 코드입니다.

사용 컴파일러는 Borland C++ 3.1이고요.

#include <stdio.h>
#include <dos.h>

typedef void interrupt (*ISR)();
ISR org;
int count = 0;
int pressed = 0;

void interrupt myisr2()
{
	_disable();
	++count;
	_enable();
}

void interrupt myisr1()
{
	_disable();
	pressed = 1;
	_enable();
	_chain_intr(myisr2);
}

int main()
{
	org = _dos_getvect(0x5);
	_dos_setvect(0x5, myisr1);
	printf("Press <Shift + PrtScr> 5 times.\n");
	while (count < 5)
	{
		if (pressed)
		{
			printf("%dth <Shift+PrtScr> key.\n");
			pressed = 0;
		}
	}

	printf("\tYou pressed <Shift + PtrScr> 5 times.\n");
	_dos_setvect(0x5, org);
	return 0;
}

그런데 컴파일을 하면 다음 내용의 오류를 내보냅니다.

Quote:
D:\Compile\c_hard>bcc test
Borland C++ Version 3.1 Copyright (c) 1992 Borland International
test.cpp:
Error test.cpp 21: Cannot convert 'void (interrupt *)()' to 'void (interrupt far
*)(...)' in function interrupt myisr1()
Error test.cpp 21: Type mismatch in parameter '__target' in call to '_chain_intr
(void (interrupt far*)(...))' in function interrupt myisr1()
Error test.cpp 26: Cannot convert 'void (interrupt far*)(...)' to 'void (interru
pt far*)()' in function main()
Error test.cpp 27: Cannot convert 'void (interrupt *)()' to 'void (interrupt far
*)(...)' in function main()
Error test.cpp 27: Type mismatch in parameter '__isr' in call to '_dos_setvect(u
nsigned int,void (interrupt far*)(...))' in function main()
Error test.cpp 39: Cannot convert 'void (interrupt far*)()' to 'void (interrupt
far*)(...)' in function main()
Error test.cpp 39: Type mismatch in parameter '__isr' in call to '_dos_setvect(u
nsigned int,void (interrupt far*)(...))' in function main()
*** 7 errors in Compile ***

Available memory 4108084

D:\Compile\c_hard>

제가 보기에는 far 포인터형과 일치하지 않아서 그렇다고 하는 것 같은데 인터넷에서 찾아봐도 어떻게 형변환을 하라는 말도 없고 코드도 모두 이런 형식이었습니다.

어떻게 하면 될까요?

그리고 추가로 getvect, setvect 함수와 _dos_getvect, _dos_setvect 함수의 차이점을 알려주시면 고맙겠습니다.

markboy의 이미지

다음 url에서 예제 소스를 보시면 이해가 빠르실 껍니다.

http://www.digitalmars.com/rtl/dos2.html#_chain_intr

덧) near, far.. 추억의 단어들이군요 :D

freesky의 이미지

답변 감사합니다. 그런데 역시 안 되네요.

개인적으로 좀 더 공부해야겠습니다.

올해에는 꼭 노트북이 생기게 해 주세요.

cppig1995의 이미지

myisr2, myisr1 함수를 void interrupt... 에서
void far interrupt... 으로 바꿔 주시고요.
ISR 형정의 typedef void interrupt (*ISR)();
역시 typedef void far interrupt (*ISR)();
로 바꿔 주시면 되겠습니다.

setvect 는 void far interrupt (*)() 형을 받고,
getvect 는 void far interrupt (*)() 형을 돌려주거든요.

아시다시피 near 함수 포인터와 far 함수 포인터 사이에는
모종의 자동 형변환 관계가 없습니다.

그럼 이만.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

freesky의 이미지

해결했습니다.

dos.h 파일을 분석하니 C++용과 C용 두 가지 함수가 있더군요.

#ifdef __cplusplus
void        _Cdecl _chain_intr ( void interrupt (far *__target)( ... ));
void interrupt( far * _Cdecl _dos_getvect( unsigned __interruptno ))( ... );
void interrupt( far * _CType getvect( int __interruptno ))( ... );
void        _Cdecl _dos_setvect( unsigned __interruptno,
                                 void interrupt( far *__isr )( ... ));
void        _CType setvect( int __interruptno,
                            void interrupt( far *__isr )( ... ));
int  inline _Cdecl peek( unsigned __segment, unsigned __offset )
                  { return( *( (int  far* )MK_FP( __segment, __offset )) ); }
char inline _Cdecl peekb( unsigned __segment, unsigned __offset )
                  { return( *( (char far* )MK_FP( __segment, __offset )) ); }
void inline _Cdecl poke( unsigned __segment, unsigned __offset, int __value )
               {( *( (int  far* )MK_FP( __segment, __offset )) = __value ); }
void inline _Cdecl pokeb( unsigned __segment, unsigned __offset, char __value )
               {( *( (char far* )MK_FP( __segment, __offset )) = __value ); }
#else
void        _Cdecl _chain_intr ( void interrupt (far *__target)( ));
void interrupt( far * _Cdecl _dos_getvect( unsigned __interruptno ))( );
void interrupt( far * _CType getvect( int __interruptno ))( );
void        _Cdecl _dos_setvect( unsigned __interruptno,
                void interrupt( far *__isr )( ));
void        _CType setvect( int __interruptno,
                void interrupt( far *__isr )( ) );

컴파일을 할 때 C++ 함수로 컴파일이 되어서 형이 맞지 않았던 것 같습니다.

myisr1()을 myisr1(...) 식으로 인터럽트 처리 관련 함수들의 형식을 모조리 바꾸니까 컴파일이 잘 됩니다.

전처리계를 잘 수정하면 될 듯한데 내공 부족으로 아직 그것까지는 모르겠군요.

어쨌든 답변 달아주신 분들, 고맙습니다.

올해에는 꼭 노트북이 생기게 해 주세요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.