문제

나는 커널의 첫 비트를 함께 해킹하려는 과정에 있습니다. 나는 현재 전체 커널을 C 코드로 컴파일하고 있으며 콘솔 창에 텍스트를 표시하고 그 모든 훌륭한 장점을 표시했습니다. 이제 키보드 입력 수락을 시작하여 실제로 물건을 사용하고 프로세스 관리를 계속할 수 있습니다.

DJGPP를 사용하여 컴파일하고 그루브로로드하고 있습니다. 또한 기본적으로 컴파일 된 C 코드로 직접 점프하는 작은 어셈블리를 사용하고 있습니다.

내가 한 모든 연구는 Keyb 내가 말할 수있는 바에 따르면, 이것은 ASCII 값을 AH에 저장하고 AL의 키 코드 또는 그 효과에 대한 무언가를 저장해야합니다. 인라인 어셈블리에서 다음 루틴을 사용하여 이것을 코딩하려고합니다.

char getc(void) 
{
    int output = 0;

    //CRAZY VOODOO CODE
    asm("xor %%ah, %%ah\n\t"
        "int $0x16"
        : "=a" (output)
        : "a" (output)
        : 

        );

    return (char)output;
}

이 코드가 호출되면 코어가 즉시 충돌합니다. (VirtualBox에서 실행 중이며 실제 하드웨어 에서이 기본을 시도 할 필요가 없다고 생각합니다.)

이제 실제로 몇 가지 질문이 있습니다. (내 코드가 Grub에서 시작되었으므로) 실제 모드로 실행되거나 보호 모드로 실행 중인지 아무도 말할 수 없었습니다. 나는 점프를 한 방향으로 만들지 않았고 프로세스 핸들러를 설정할 때까지 실제 모드로 실행할 계획이었습니다.

그래서, 실제 모드에서 실행 중이라고 가정하면, 내가 무엇을 잘못하고 있으며 어떻게 해결해야합니까? 기본적인 getc 루틴, 바람직하게는 차단이 필요하지만 Google이 이것에 대해 전혀 도움이되면 대담하게 될 것입니다. 일단 그렇게 할 수 있으면 나머지는 거기에서 할 수 있습니다.

내가 여기서 묻는 것이 무엇인지, 내가 올바른 길을 가고 있는가? 일반적 으로이 레벨에서 키보드 입력을 얻는 방법은 무엇입니까?

편집 : oohh ... 그래서 보호 모드로 실행 중입니다. 이것은 확실히 실제 모드 기능에 액세스하려는 충돌을 설명합니다.

그렇다면 보호 모드에서 키보드 IO에 액세스하는 방법을 찾고 있다고 생각합니다. 나는 그것을 스스로 찾을 수 있을지 모르지만, 누군가가 자유롭게 느끼는 사람이라면 자유롭게 느껴집니다. 다시 한 번 감사드립니다.

도움이 되었습니까?

해결책

GCC로 컴파일하는 경우 미친 ".Code16GCC"를 사용하지 않는 한 Linux 커널이 사용하는 트릭 (매우 의심). 실제 모드에있을 수는 없습니다. Grub Multiboot 사양을 사용하는 경우 Grub 자체가 보호 모드로 전환됩니다. 따라서 다른 사람들이 지적했듯이 8042 호환 키보드/마우스 컨트롤러와 직접 대화해야합니다. USB 키보드/마우스이고 8042 에뮬레이션이 비활성화되지 않는 한 USB 스택이 필요한 경우 (그러나 더 간단한 키보드/마우스에는 "부팅"프로토콜을 사용할 수 있습니다).

OS 커널을 쓰는 것이 간단하다고 말한 사람은 아무도 없습니다.

다른 팁

당신이 가진 코드는 실제 모드 BIOS 서비스에 액세스하려고합니다. 보호 모드로 실행중인 경우 커널을 작성하는 것을 고려하고있는 경우 인터럽트가 작동하지 않습니다. 다음 중 하나를 수행해야합니다.

  • CPU를 실제 모드로 묶고 인터럽트 벡터 테이블이 올바른지 확인하고 가지고있는 실제 모드 코드를 사용하거나
  • 자신의 보호 모드 키보드 핸들러를 작성하십시오 (예 : In/Out 지침 사용).

첫 번째 솔루션에는 런타임 성능 오버 헤드가 포함됩니다. 두 번째는 키보드 IO에 대한 정보가 필요합니다.

나는 geekos 조각을하는 것 같습니다

In_Byte(KB_CMD);

그리고

In_Byte(KB_DATA);

스캔 코드를 가져 오기 위해. 나는 그것을 올렸다 : keyboard.c 그리고 키보드 .H. KB_CMD 그리고 KB_DATA 각각 0x64 및 0x60입니다. 아마도 이것이 Intr : 1의 인터럽트 핸들러에서 수행된다는 것을 지적 할 수 있습니다.

당신은 옳은 일을하고 있지만, DJGPP는 보호 모드 출력 만 생성되며 인터럽트를 호출 할 수 없다는 것을 기억하는 것 같습니다. 다른 사람들이 제안한 것처럼 실제 모드로 떨어질 수 있습니까, 아니면 하드웨어를 직접 해결하는 것을 선호합니까?

설명의 목적으로, 당신이 글을 쓰고 있다고 가정 해 봅시다. 모든 것 어셈블리 언어 직접 부팅 로더와 커널 (* 기침*이 작업을 수행했습니다).

실제 모드에서는 BIOS에서 나오는 인터럽트 루틴을 사용할 수 있습니다. 인터럽트 벡터를 자신의 것으로 교체 할 수도 있습니다. 그러나 모든 코드는 16 비트 코드입니다 이진 호환되지 않습니다 32 비트 코드로.

보호 모드로 도착하기 위해 몇 번의 연소 후프를 뛰어 넘어 (인터럽트 컨트롤러를 재 프로그래밍하여 IBM이 PC에서 인텔 보존 인터럽트를 사용했다는 사실을 해결하기 위해) 16 및 32 비트를 설정할 수있는 기회가 있습니다. 코드 세그먼트. 16 비트 코드를 실행하는 데 사용할 수 있습니다. 따라서 이것을 사용하여 getchar 인터럽트에 액세스 할 수 있습니다!

... 그다지 아닙니다. 이 인터럽트가 작동하려면 실제로 키보드 버퍼에 다른 ISR이 넣은 데이터가 필요합니다. 키가 눌렀을 때 키보드에 의해 트리거되는 것입니다. 보호 모드에서 BIOS ISRS를 실제 하드웨어 ISR로 사용하는 다양한 문제가 있습니다. 따라서 BIOS 키보드 루틴은 쓸모가 없습니다.

반면에 BIOS 화상 통화는 하드웨어 트리거 구성 요소가 없기 때문에 괜찮습니다. 16 비트 코드 세그먼트를 준비해야하지만 제어중인 경우 BIOS 인터럽트를 사용하여 비디오 모드와 이러한 종류의 것을 전환 할 수 있습니다.

키보드로 돌아 가기 : 필요한 내용 (모든 코드를 작성한다고 가정)은 키보드 드라이버를 작성하는 것입니다. 당신이 마조히스트가 아니라면 (나는 하나) 거기에 가지 마십시오.

제안 : 실제 모드로 멀티 태스킹 커널을 작성하십시오. (16 비트 모드입니다.) 모든 BIOS 인터럽트를 사용할 수 있습니다! 메모리 보호를받지는 않지만 타이머 인터럽트를 연결하여 여전히 선제 적 멀티 태스킹을받을 수 있습니다.

그냥 아이디어 :보고 있습니다 DOS를위한 그루브 출처 (ASM.S), console_checkkey 기능은 BIOS를 사용하고 있습니다 INT 16H Function 01, 당신이하려고하는 것처럼, 00. 키가 입력되기를 기다리는 지 확인하고 싶을 수도 있습니다.

그만큼 console_checkkey 코드는 BIOS를 사용하기 위해 CPU를 실제 모드로 설정합니다. @skizz가 제안했습니다.

Grub 함수를 직접 사용해 볼 수도 있습니다 (실제 모드에 여전히 맵핑 된 경우).

읽기 어셈블리 소스에 대한 메모 :이 버전에서

movb    $0x1, %ah

상수 바이트 (0x1)를 등록하기 위해 이동하는 것을 의미합니다 %ah

그만큼 console_checkkey Grub Asm.s에서 :

/*
 * int console_checkkey (void)
 *  if there is a character pending, return it; otherwise return -1
 * BIOS call "INT 16H Function 01H" to check whether a character is pending
 *  Call with   %ah = 0x1
 *  Return:
 *      If key waiting to be input:
 *          %ah = keyboard scan code
 *          %al = ASCII character
 *          Zero flag = clear
 *      else
 *          Zero flag = set
 */
 ENTRY(console_checkkey)
  push  %ebp
  xorl  %edx, %edx

  call  EXT_C(prot_to_real) /* enter real mode */

  .code16

  sti       /* checkkey needs interrupt on */

  movb  $0x1, %ah
  int   $0x16

  DATA32    jz  notpending

  movw  %ax, %dx
  //call    translate_keycode
  call  remap_ascii_char
  DATA32    jmp pending

notpending:
  movl  $0xFFFFFFFF, %edx

pending:
  DATA32    call    EXT_C(real_to_prot)
  .code32

  mov   %edx, %eax

  pop   %ebp
  ret

키보드 컨트롤러 폴링 예 :

Start:
      cli
      mov al,2        ; dissable IRQ 1
      out 21h,al
      sti

;--------------------------------------
; Main-Routine
AGAIN:
      in al,64h       ; get the status
      test al,1       ; check output buffer
      jz short NOKEY
      test al,20h     ; check if it is a PS2Mouse-byte
      jnz short NOKEY
      in al,60h       ; get the key

; insert your code here (maybe for converting into ASCII...)

NOKEY:
      jmp AGAIN
;--------------------------------------
; At the end
      cli
      xor al,al       ; enable IRQ 1
      out 21h,al
      sti
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top