2016-06-23 7 views
0

최근에 나는 간단한 MSDOS 게임을 코딩하는 것이 재미있을 것이라고 결정했습니다. 바늘 말하기를, 나는 키보드 이벤트를 처리하기위한 코드가 필요하다.키보드 처리기가 segfault (djgpp)를 발생시킵니다

이것은 내가 테스트 해낸 것입니다 :

int i, c = 0; 
for (i = 0; i < 10; i++) 
{ 
    asm 
    (
     "mov $0x00, %%ah   \n" 
     "mov $0x00, %%al   \n" 
     "int $0x16    \n" 
     //"jnz keydn    \n" 
     //"mov $0x00, %%al  \n" 
     //"keydn:    \n" 
     "movw %%ax, (%0)   \n" 
      : "=r"(c) 
    ); 

    printf("%d\n", c & 0xFF); 
} 

코드는 키를 누를 때까지 기다린 다음 문자의 ASCII 값을 출력 할 예정이다. 백 스페이스 또는 esc과 같은 키를 누르지 않으면 세그먼테이션 오류가 발생하고 모든 것이 예상대로 작동합니다.

enter image description here

내가 조립에 익숙 해요,하지만 정말이 오류의 원인이 무엇인지 알아낼 수 없습니다.

내가 djgpp 컴파일 및 DosBox

모두에서 실행 파일을 실행이 정보를 기반으로 여기에 제공된 :

사전에 감사합니다! :)

+1

''mov $ 0x00, %% ah \ n ""mov $ 0x00, %% al \ n "은 xor %% ax, %% ax \ n"'또는 그 이상으로 대체 할 수 있습니다. 입력 피연산자를 사용하여 템플릿에 '0'을 전달합니다 (레지스터 'a'는 입력 및 출력 피연산자가 될 수 있음). 이것은 템플릿 자체가 _AX_ 레지스터를 0으로 만들 필요가 없게합니다. –

+0

@MichaelPetch 맞아요, 어떻게 작동하는지 이해합니다.하지만 전에 말했듯이, 나는 전에 벌거 벗은 어셈블리를 사용하지 않았기 때문에 모든 것을 가능한 한 간단하게 유지하려고했습니다. 어쨌든, 실행 속도가 향상 되었습니까? – Jacajack

+0

예, 제약이있는 메모리 환경 용으로 작성하는 경우 인코딩 할 메모리가 적습니다. –

답변

3

이것은 확실히 깨졌습니다. movw %%ax, (%0): "=r"(c) 출력 피연산자 인 피연산자 0에 의해 주어진 주소에서 메모리에 쓰려고 시도하며 초기화되지 않았습니다. 또한 포인터가 아닙니다.

asm 
    (
     "mov $0x00, %%ah   \n" 
     "mov $0x00, %%al   \n" 
     "int $0x16    \n" 
      : "=a"(c) 
    ); 

추신 : 디버거를 사용하거나 적어도 코드와 함께 레지스터 덤프를 상호 참조하는 방법을 배우십시오.

+1

고마워요! 문제를 해결하고 지금은 매력처럼 작동합니다. 불행히도 DOS 디버거에 익숙하지 않아서 애처로운 어셈블리 기술을 향상 시키려고합니다. – Jacajack