Linus Torvalds 에뮬레이션 : 처음부터 자신 만의 운영 체제 만들기 (VI)

음, 약간의 괄호 뒤에 우리는 튜토리얼 시리즈를 계속합니다. 이전 코드로 돌아가면 32으로 나눈 ISR이 있어야 합니다. 이제 메시지를 넣은 나머지 ISR(처음 XNUMX개)을 채워야 합니다. 이제 인터럽트 프로그래밍을 계속할 것입니다. 인터럽트 요청. 이러한 IRQ는 키보드, 마우스, 프린터 등과 같은 하드웨어 장치에서 생성됩니다. 처음에 처음 8개의 IRQ는 IDT 위치 8에서 15까지 자동으로 매핑됩니다. 처음 32개를 예외에 사용했기 때문에 이제 다시 매핑해야 합니다. IRQ를 32에서 45로 설정합니다. 이렇게 하려면 먼저 IRQ를 다시 매핑해야 합니다.

void ND::IRQ::Remap(int pic1, int pic2)
{
#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01
/* send ICW1 */
ND::Ports::OutputB(PIC1, ICW1);
ND::Ports::OutputB(PIC2, ICW1);
/* send ICW2 */
ND::Ports::OutputB(PIC1 + 1, pic1); /* remap */
ND::Ports::OutputB(PIC2 + 1, pic2); /* pics */
/* send ICW3 */
ND::Ports::OutputB(PIC1 + 1, 4); /* IRQ2 -> connection to slave */
ND::Ports::OutputB(PIC2 + 1, 2);
/* send ICW4 */
ND::Ports::OutputB(PIC1 + 1, ICW4);
ND::Ports::OutputB(PIC2 + 1, ICW4);
/* disable all IRQs */
ND::Ports::OutputB(PIC1 + 1, 0xFF);
}

이제 IRQ를 설치하는 함수를 만듭니다.

void ND::IRQ::Install()
{
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_BLACK);
ND::Screen::PutString("\nInstalling IRQ...");
ND::IRQ::Remap(0x20,0x28);
ND::IDT::SetGate(32,(unsigned)ND::IRQ::IRQ1,0x08,0x8E);
ND::IDT::SetGate(33,(unsigned)ND::IRQ::IRQ2,0x08,0x8E);
ND::IDT::SetGate(34,(unsigned)ND::IRQ::IRQ3,0x08,0x8E);
ND::IDT::SetGate(35,(unsigned)ND::IRQ::IRQ4,0x08,0x8E);
ND::IDT::SetGate(36,(unsigned)ND::IRQ::IRQ5,0x08,0x8E);
ND::IDT::SetGate(37,(unsigned)ND::IRQ::IRQ6,0x08,0x8E);
ND::IDT::SetGate(38,(unsigned)ND::IRQ::IRQ7,0x08,0x8E);
ND::IDT::SetGate(39,(unsigned)ND::IRQ::IRQ8,0x08,0x8E);
ND::IDT::SetGate(40,(unsigned)ND::IRQ::IRQ9,0x08,0x8E);
ND::IDT::SetGate(41,(unsigned)ND::IRQ::IRQ10,0x08,0x8E);
ND::IDT::SetGate(42,(unsigned)ND::IRQ::IRQ11,0x08,0x8E);
ND::IDT::SetGate(43,(unsigned)ND::IRQ::IRQ12,0x08,0x8E);
ND::IDT::SetGate(44,(unsigned)ND::IRQ::IRQ13,0x08,0x8E);
ND::IDT::SetGate(45,(unsigned)ND::IRQ::IRQ14,0x08,0x8E);
ND::IDT::SetGate(46,(unsigned)ND::IRQ::IRQ15,0x08,0x8E);
ND::IDT::SetGate(47,(unsigned)ND::IRQ::IRQ16,0x08,0x8E);
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_GREEN);
ND::Screen::PutString("done");
asm volatile("sti");
}

asm의 판단 스티치 IRQ를 활성화합니다. 이제 우리는 ISR과 비슷한 것을 사용합니다. 기본 IRQ의 기능:

void ND::IRQ::IRQ1()
{
asm volatile(
"cli \n"
"pushl 0\n"
"pushl 32\n"
"jmp ND_IRQ_Common"
);
}

공통 부분(ISR과 동일):

extern "C"
void ND_IRQ_Common()
{
asm volatile(
"pusha \n"
"push %ds\n"
"push %es\n"
"push %fs\n"
"push %gs\n"
"movw $0x10, %ax \n"
"movw %ax, %ds \n"
"movw %ax, %es \n"
"movw %ax, %fs \n"
"movw %ax, %gs \n"
"movl %esp, %eax \n"
"push %eax \n"
"movl $ND_IRQ_Handler, %eax \n"
"call *%eax \n"
"popl %eax \n"
"popl %ds \n"
"popl %es \n"
"popl %fs \n"
"popl %gs \n"
"popa \n"
"addl 8, %esp \n"
"iret \n"
);
}

그리고 기본 핸들러:

extern "C"
void ND_IRQ_Handler(struct regs* r)
{
void (*handler)(struct regs *r);
if(r->int_no >= 40)
{
ND::Ports::OutputB(0xA0,0x20);
}
ND::Ports::OutputB(0x20,0x20);
}

이것으로 우리는 IRQ가 아직 아무것도 하지 않더라도 이미 활성화되어 있어야 합니다. 다음 장에서는 시계나 키보드와 같은 이러한 IRQ에서 데이터를 얻는 방법을 살펴보겠습니다.

NextDivel-IRQ


이상으로 오늘의 포스팅을 마칩니다. 당신이 지금 확인할 수 있었기 때문에 나는 다른 문제로 인해 덜 정기적으로 글을 씁니다. 그래도 더 완성된 운영체제가 나올때까지 계속 하겠습니다


코멘트를 남겨주세요

귀하의 이메일 주소는 공개되지 않습니다. 필수 필드가 표시되어 있습니다 *

*

*

  1. 데이터 책임자 : Miguel Ángel Gatón
  2. 데이터의 목적 : 스팸 제어, 댓글 관리.
  3. 합법성 : 귀하의 동의
  4. 데이터 전달 : 법적 의무에 의한 경우를 제외하고 데이터는 제 XNUMX 자에게 전달되지 않습니다.
  5. 데이터 저장소 : Occentus Networks (EU)에서 호스팅하는 데이터베이스
  6. 권리 : 귀하는 언제든지 귀하의 정보를 제한, 복구 및 삭제할 수 있습니다.

  1.   aitor_cz

    Adrian에게 대단히 감사합니다. 시간이 나는 대로(지금은 운영 체제 때문에 매우 바쁩니다) 단계별 자습서를 시도해 보겠습니다.

  2.   루비

    튜토리얼에 대해 대단히 감사합니다.

  3.   사스케

    한 가지 질문이 프로그래밍 언어를 기반으로 프로젝트를 수행하고 있습니다.
    *HTML5
    *CSS3
    *자바
    제 질문은 이 프로젝트를 실행 가능하게 하여 사용자가 Linux 및 Windows와 같은 운영 체제에서 사용할 수 있도록 하는 것입니다. 그 방법을 알려주실 수 있습니까?

    1.    AdrianArroyoStreet

      이것과는 상관없지만 그래도 답변해드리겠습니다. HTML5와 Java는 잘 어울리지 않기 때문에 Java가 아닌 HTML3, CSS5 및 JavaScript가 될 것 같습니다. HTML5를 사용하면 지금까지 인터넷에서 액세스할 수 있는 웹 사이트를 만들 수 있습니다. 로컬로 만들고 싶다면 Firefox OS 및 Chrome OS 앱으로 패키징할 수 있습니다. 각 운영 체제에서 실행 파일을 원하는 경우 Gecko 엔진으로 XUL(따라서 요소 내부의 HTML5)을 실행하는 도구인 XUL Runner를 살펴보십시오.

    2.    소 이드 페레즈

      Java 프레임 또는 패널은 매우 좋은 옵션입니다. Java 프레임 클래스를 웹 브라우저로 사용하여 창에서 실행 가능한 앱을 만들었지만 페이지에 사용하는 대신 코드에 직접 경로를 지정하고 PHP를 사용하여 Java 문을 실행합니다. 그것을 처리하는 .jar의 그것을 통해. HTML5, CSS3 및 JavaScript를 사용하는 것이 좋습니다. Adrian이 말했듯이 Java는 Html5에서 치명적이며 많은 골칫거리를 가져 왔습니다.

  4.   러반

    자신의 프로그래밍 언어를 만드는 방법에 대한 자습서가 좋을 것입니다.

  5.   이반

    운영 체제를 구축하는 방법에 대한 이 일련의 기사는 매우 훌륭하며 많은 것을 배울 수 있습니다. 다음 항목을 기다리고 있습니다. 이미 OS에 키보드를 갖고 싶습니다. 나는 git 코드를 엉망으로 만들었고 포트 0x60 및 0x64에서 작동하도록 할 수 없었습니다. 키보드의 경우 키를 누르는 인터럽트가 있다고 생각했지만.

    1.    AdrianArroyoStreet

      실제로 중단 없이 키보드 입력을 받을 수 있지만 포트 0x60에서 ND::Ports::InputB로 읽어야 합니다. 그러나 이상적인 방법은 IRQ 인터럽트를 사용하는 것입니다. 나는 현재 그것을하려고 노력하고 있으며 그것 때문에 진행하는 데 시간이 조금 더 걸립니다.

      1.    카를로 소르 타

        안녕하세요 Adrian, 저는 코드를 확인하고 있었는데 코드가 하는 일과 몇 가지 작은 것들을 이해하는 데 얼마나 도움이 되었는지에 깊은 인상을 받았습니다.

        작동 방식에 대해 몇 가지 질문이 있으며 소스는 귀하의 GIT에서 가져온 것입니다.

        1.- IRQ 부분에서 IDT의 0에서 32까지의 위치가 예외에 대해, 32(0x20)에서 45(0x2D)까지의 IRQ가 사용되었다고 언급했지만 총 16개의 IRQ가 리매핑되지 않을까요? 0x20에서 0x30으로?

        2.- IRQ 부분에서 setgates를 IDT 섹션으로 보냈는지 확인하십시오. 그것들을 분리했을 때 더 이상 0으로 나누기 예외를 생성하지 않는다는 것을 알았습니다. 따라서 수정될 때마다 IDT Flush()를 추가해야 합니다. 타이머를 설정할 때 IDT가 변경되고 0으로 나누기가 작동하지 않는 이유는 무엇입니까?

        3.- 무엇이 실행되고 있는지를 나타내는 것으로 코드를 추적하려고 했고(단계별로 디버깅하지 않기 위해) IRQ가 작동하지 않는다는 것을 깨달았습니다. 다른 것을 등록해야 합니까? IRQ 인터럽트가 생성됩니까?

        1.    카를로 소르 타

          정보가 포함된 다음 링크를 찾았다는 사실을 언급하는 것을 잊었습니다.
          http://arstechnica.com/civis/viewtopic.php?f=20&t=899001
          http://www.superfrink.net/athenaeum/OS-FAQ/os-faq-pics.html
          http://orga2.exp.dc.uba.ar/data/downloads/clasespracticas/interrupciones2_clase_17.pdf
          http://www.intel-assembler.it/PORTALE/4/231468_8259A_PIC.pdf

          분명히 IRQ 관리를 위해 PIC, APIC, IOAPIC 중 어떤 유형의 핸들러가 사용되는지 고려해야 합니다. . .등. IRQ를 동적으로 처리할 수 있는 방법이 있습니까, 아니면 운을 시험해 볼 필요가 있습니까?

  6.   카를로 소르 타

    좋은 오후 아드리안.

    나는 그것이 IRQ에 문제가 있다는 것을 알았고 따라서 코드에서 발전할 수 없었습니다. 나는 프로젝트의 사본을 가져와 분석하기 시작했습니다. 인터럽트를 만들 때 struct reg의 레코드를 인쇄하기 위해 화면 인쇄에 기능을 추가했습니다. 레지스트리가 실행 중이고 여전히 이유를 찾을 수 없다는 몇 가지 작은 것을 발견했습니다. 키보드 중단에 대한 타이머 중단을 테스트로 변경했는데 제대로 작동하지만 문제를 찾을 수 없습니다. 이 좋은 게시물을 계속 도와주시겠습니까? 😀

    나는 당신에게 링크를 남깁니다 (Mageia를 사용하고 Grub2를 사용하기 때문에 약간의 수정이 있습니다. VirtualBox를 사용하여 테스트하고 있습니다)
    https://www.mediafire.com/?93psrgaoozatse8

    여러분의 세심한 답변을 기다리며 궁금한 점이나 필요한 사항이 있으시면 도움을 드리고 싶습니다 🙂

    1.    카를로 소르 타

      ISR이 작동하지 않았기 때문에 KernelPanic도 확인했다는 점을 언급하는 것을 잊었습니다. 스택 맨 위에서 동일한 문제가 발생하여 값이 유출되고 있고 이것이 내 컴파일러인지 또는 문제가 있는지 알 수 없습니다. Mageia 4.8.2와 함께 GCC 4를 사용합니다.

    2.    AdrianArroyoStreet

      나는 당신이 프로젝트에서 나를 돕는 것을 정말 좋아합니다. 타이머에 정말 갇혔는데 왜 작동하지 않는지 모르겠습니다. 나는 많은 것을 수정하는 테스트를 수행했지만 나오지 않았습니다. 현재는 코드를 편집할 수 없지만(휴가 중) 최대한 빨리 살펴보겠습니다. 일반적인 것으로 보이는 이 문제에 대한 정보가 포함된 링크를 제공합니다. http://wiki.osdev.org/I_Cant_Get_Interrupts_Working

      예외에 관해서는 어딘가에 문제가 있음이 분명하지만 ASM에서 "sti"를 호출하여 활성화해야 한다는 것을 기억하는 것 같습니다.

      1.    카를로 소르 타

        답장을 보내 주셔서 감사합니다. 그렇습니다. 인터럽트는 실패했지만 스택에 코드를 삽입할 때 문제가 있었고 캐스팅 문제였으니 링크를 확인하고 테스트를 해보겠습니다. 해결하면 알려드리고 해결되지 않으면 진행 상황을 알려 드리겠습니다. 행복한 휴일 🙂

      2.    카를로 소르 타

        조립된 코드를 볼 수 있는 방법이 없나요? 뭔가 이상한 일이 일어나고 있는데 무엇을 찾을 수 없나요? 이 화면을 보세요(링크는 맨 끝에 두었습니다) 뭔가 이상합니다. IRQ 2 기능(키보드)에서 스택에 값 0과 0x20(32, 테스트용으로 배열)을 입력한 다음 pushal(32비트 GPR 레지스터), 세그먼테이션 레지스터, 스택의 맨 위를 차례로 입력한 다음 IRQ 핸들러를 호출합니다. 나는 각 스택을 보기 시작했고 분명히 그것은 순서에 있지만 VM의 출력을 관찰할 수 있다면 그것이 하나 이상의 요소를 쌓는 것을 볼 수 있습니다. 어디를 찾을 수 없습니다. 그것이 0x10이라는 것만 알고 구조가 잘못되었습니다. 이것은 레코드 구조입니다.

        구조체{
        uint32_t gs, fs, es, ds; /* 마지막 초 푸시 */
        uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* 'pushal'에 의해 푸시됨 */
        uint32_t int_no, err_code; /* 에러 코드 */
        uint32_t eip, cs, eflags, useresp, ss; /* 인터럽트 시 스택 */
        };

        그것은 맨 위에 하나 이상의 요소를 배치하고 분명히 모든 것이 있어야 할 때 쌓이는 경우 쌓인 위치를 찾을 수 없다는 것이 나를 귀찮게 합니다. 그게 뭔지 아세요?

        http://www.subeimagenes.com/img/sin-titulo-1036729.jpg

  7.   카를로 소르 타

    키보드 인터럽트는 작동하지만 타이머는 작동하지 않습니다. 오류는 컴파일 방식에 있었고 최종 개체를 보기 위해 objdump를 사용했고 "asm volatile"을 사용하여 입력한 각 함수에도 pushl ebp, mov ebp, esp가 수반되는 것으로 나타났습니다. 그런 다음 popl ebp를 추가하여 초기 스택을 복원하면 반드시 인수를 전달할 것입니다. 여기에 확인하려는 사람들을 위한 코드를 첨부하고 그들이 타이머에 의해 중단이 생성되지 않는 이유를 발견할 수 있다면 알고 싶습니다. 멀티태스킹에 대해 이야기하는 링크를 첨부합니다. http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html
    다음 레벨
    https://www.mediafire.com/?kmo83dxyzc7c3cz

    1.    AdrianArroyoStreet

      알겠어요. Timer PIC의 활성화에 영향을 준 다른 곳의 버그였습니다. 특히 IRQ 리맵에는 수정해야 하는 두 줄이 있었습니다. 웹사이트에서 코드를 볼 수 있었던 덕분에 그 시점에서 뭔가 다른 코드가 있었습니다! 변경 사항은 다음과 같습니다.
      ND::포트::출력B(PIC1 + 1, 0xFF);
      ND::포트::출력B(PIC2 + 1, 0xFF);

      확실하지는 않지만 0xFF(비활성화됨을 나타냄)의 값을 0x00(활성화됨을 나타냄)으로 변경해야 했지만 작동합니다. GitHub에서 코드를 업데이트했습니다. 이 문제로 인해 조금 포기했던 프로젝트를 도와주셔서 정말 정말 감사합니다. 시간

      1.    카를로 소르 타

        천만에요, 주제에 대한 다음 업데이트를 기대하고 무엇이든 저에게 의지하겠습니다 🙂 (Y)

      2.    카를로 소르 타

        키보드 문자열 캡처 루틴을 변경하십시오. 키를 놓을 때 읽고 버퍼에 0을 마운트하기 때문에 읽기에 문제가 발생하고 결국 올바른 인쇄가 작동하도록 '\n'을 »로 변경합니다.

  8.   소 이드 페레즈

    안녕하세요, 전체 게시물을 읽었습니다. 실제로는 2개의 게시물을 넘지 않지만 정말 좋습니다. 모든 것을 저장했지만 "c"를 알고 있기 때문에 이해하려면 C++ 및 posix를 공부해야 합니다. (저는 그 프로그래밍 언어를 좋아합니다) 하지만 C++은 c OO이지만 실제로 작업한 적이 없습니다. 그는 Google에서 몇 가지 자습서를 읽은 다음 다시 돌아왔습니다. 이것은 매우 흥미롭고 한 가지 질문입니다. 창 시작이 Linux와 비슷합니까?

    1.    AdrianArroyoStreet

      Windows로 부팅하는 것은 x86 프로세서로 시스템을 부팅하는 방법이며 그 위에 구축된 운영 체제의 영향을 거의 받지 않는다는 점에서 유사합니다. 어쨌든 실제로 우리를 부팅하는 것이 아니라 GRUB를 부팅합니다. Linux를 부팅하도록 설계된 GRUB는 Windows와 이 경우 NextDivel을 부팅할 수 있습니다.

      1.    소리

        감사합니다. 제가 하고 싶은 일이 가능하다는 뜻입니다. 저는 이미 C++를 공부하고 있고 몇 가지 앱을 만들고 플래시 드라이브에 시스템을 설치했으며 더 자세히 공부하고 있습니다. 아주 좋은 게시물입니다.