Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调试三重故障_C++_Assembly_X86_Interrupt Handling_Osdev - Fatal编程技术网

C++ 调试三重故障

C++ 调试三重故障,c++,assembly,x86,interrupt-handling,osdev,C++,Assembly,X86,Interrupt Handling,Osdev,我正在尝试一个(wyoos.org),我很难让中断正常工作。当我试图在Virtualbox中运行我的操作系统时,我会在激活中断后的某个时间出现三重故障。我了解到这可能是因为我的全局描述符表没有正确设置。可能我正试图跳入一个数据块 我敢肯定,当一个中断被触发时,我不会处理它,但我很难调试它。有人能给我指一下正确的方向吗 我的中断处理由三个文件组成,interruptstubs.s,interrupts.h和interrupts.cpp #interruptstubs.s .set IRQ_BAS

我正在尝试一个(wyoos.org),我很难让中断正常工作。当我试图在Virtualbox中运行我的操作系统时,我会在激活中断后的某个时间出现三重故障。我了解到这可能是因为我的全局描述符表没有正确设置。可能我正试图跳入一个数据块

我敢肯定,当一个中断被触发时,我不会处理它,但我很难调试它。有人能给我指一下正确的方向吗

我的中断处理由三个文件组成,
interruptstubs.s
interrupts.h
interrupts.cpp

#interruptstubs.s

.set IRQ_BASE, 0x20

.section .text
.extern _ZN16InterruptManager15HandleInterruptEhj
.global _ZN16IterruptManager26IgnoreInterruptRequestEv

.macro HandleException num
.global _ZN16InterruptManager16HandleException\num\()Ev
_ZN16InterruptManager16handleException\num\()Ev:
    movb $\num, (interruptnumber)
    jmp int_bottom
.endm

.macro HandleInterruptRequest num
.global _ZN16InterruptManager26HandleInterruptRequest\num\()Ev
_ZN16InterruptManager26handleInterruptRequest\num\()Ev:
    movb $\num + IRQ_BASE, (interruptnumber)
    jmp int_bottom
.endm

HandleInterruptRequest 0x00
HandleInterruptRequest 0x01

int_bottom:

  pusha
  pushl %ds
  pushl %es
  pushl %fs
  pushl %gs

  pushl %esp
  push (interruptnumber)
  call  _ZN16InterruptManager15HandleInterruptEhj
  # addl $5, %esp
  movl %eax, %esp

  popl %gs
  popl %fs
  popl %es
  popl %ds
  popa

_ZN16IterruptManager26IgnoreInterruptRequestEv:
  iret

  .data
interruptnumber:   .byte 0
打断

#ifndef __INTERRUPTS_H
#define __INTERRUPTS_H

#include "types.h"
#include "port.h"
#include "gdt.h"

class InterruptManager {
 public:
  InterruptManager(GlobalDescriptorTable* gdt);
  ~InterruptManager();

  static void Activate();

  static uint32_t HandleInterrupt(uint8_t interruptNumber, uint32_t esp );

  static void InterruptIgnore();
  static void HandleInterruptRequest();
  static void HandleInterruptRequest0x00();
  static void HandleInterruptRequest0x01();

 protected:
  struct GateDescriptor {
    uint16_t handlerAddressLowBits;
    uint16_t gdt_codeSegmentSelector;
    uint8_t reserved;
    uint8_t access_rights;
    uint16_t handlerAddressHighBits;
  } __attribute__((packed));

  static GateDescriptor interruptDescriptorTable[256];

  struct InterruptDescriptorTablePointer
  {
    uint16_t size;
    uint32_t base;
  } __attribute__((packed));

  static void SetInterruptDescriptorTableEntry(
                                               uint8_t interruptNumber,
                                               uint16_t codeSegmentSelectorOffset,
                                               void (*handler)(),
                                               uint8_t DescriptorPrivilegeLevel,
                                               uint8_t DescriptorType);

  Port8BitSlow picMasterCommand;
  Port8BitSlow picMasterData;
  Port8BitSlow picWorkerCommand;
  Port8BitSlow picWorkerData;

};

#endif
中断.cpp

#ifndef __INTERRUPTS_H
#define __INTERRUPTS_H

#include "types.h"
#include "port.h"
#include "gdt.h"

class InterruptManager {
 public:
  InterruptManager(GlobalDescriptorTable* gdt);
  ~InterruptManager();

  static void Activate();

  static uint32_t HandleInterrupt(uint8_t interruptNumber, uint32_t esp );

  static void InterruptIgnore();
  static void HandleInterruptRequest();
  static void HandleInterruptRequest0x00();
  static void HandleInterruptRequest0x01();

 protected:
  struct GateDescriptor {
    uint16_t handlerAddressLowBits;
    uint16_t gdt_codeSegmentSelector;
    uint8_t reserved;
    uint8_t access_rights;
    uint16_t handlerAddressHighBits;
  } __attribute__((packed));

  static GateDescriptor interruptDescriptorTable[256];

  struct InterruptDescriptorTablePointer
  {
    uint16_t size;
    uint32_t base;
  } __attribute__((packed));

  static void SetInterruptDescriptorTableEntry(
                                               uint8_t interruptNumber,
                                               uint16_t codeSegmentSelectorOffset,
                                               void (*handler)(),
                                               uint8_t DescriptorPrivilegeLevel,
                                               uint8_t DescriptorType);

  Port8BitSlow picMasterCommand;
  Port8BitSlow picMasterData;
  Port8BitSlow picWorkerCommand;
  Port8BitSlow picWorkerData;

};

#endif
(v2_ordergroove-py27) ~/s/wyoos ❯❯❯ cat interrupts.cpp
#include "interrupts.h"

void printf(const char* str);

InterruptManager::GateDescriptor InterruptManager::interruptDescriptorTable[256];

void InterruptManager::SetInterruptDescriptorTableEntry(
        uint8_t interruptNumber,
        uint16_t codeSegmentSelectorOffset,
        void (*handler)(),
        uint8_t DescriptorPrivilegeLevel,
        uint8_t descriptorType)
{
  printf("\nGDT Entry Start\n");
  interruptDescriptorTable[interruptNumber].handlerAddressLowBits = ((uint32_t)handler) & 0xFFFF;
  interruptDescriptorTable[interruptNumber].handlerAddressHighBits = (((uint32_t)handler) >> 16) & 0xFFFF;
  interruptDescriptorTable[interruptNumber].gdt_codeSegmentSelector = codeSegmentSelectorOffset;

  const uint8_t IDT_DESC_PRESENT = 0x00;
  interruptDescriptorTable[interruptNumber].access_rights = IDT_DESC_PRESENT | descriptorType | (DescriptorPrivilegeLevel << 5);
  interruptDescriptorTable[interruptNumber].reserved = 0;
  printf("\nGDT Entry End\n");
}

InterruptManager::InterruptManager(GlobalDescriptorTable* gdt)
  : picMasterCommand(0x20),
    picMasterData(0x21),
    picWorkerCommand(0xA0),
    picWorkerData(0xA1)
{
  uint16_t CodeSegment = gdt->CodeSegmentSelector();
  const uint8_t IDT_INTERRUPT_GATE = 0xE;

  for(uint16_t i = 0; i < 256; i++) {
    SetInterruptDescriptorTableEntry(i, CodeSegment, &InterruptIgnore, 0, IDT_INTERRUPT_GATE);
  }
  SetInterruptDescriptorTableEntry(0x20, CodeSegment, &HandleInterruptRequest0x00, 0, IDT_INTERRUPT_GATE);
  SetInterruptDescriptorTableEntry(0x21, CodeSegment, &HandleInterruptRequest0x01, 0, IDT_INTERRUPT_GATE);

  picMasterCommand.Write(0x11);
  picWorkerCommand.Write(0x11);

  picMasterData.Write(0x20);
  picWorkerData.Write(0x20);

  picMasterData.Write(0x04);
  picWorkerData.Write(0x02);

  picMasterData.Write(0x01);
  picWorkerData.Write(0x01);

  picMasterData.Write(0x00);
  picWorkerData.Write(0x00);

  InterruptDescriptorTablePointer idt;
  idt.size = 256 * sizeof(GateDescriptor) - 1;
  idt.base = (uint32_t)interruptDescriptorTable;
  asm volatile("lidt %0" : : "m" (idt));
}

void InterruptManager::InterruptIgnore() {

}

void InterruptManager::HandleInterruptRequest0x01() {
 printf("Handle 0x01"); 
}

void InterruptManager::HandleInterruptRequest0x00() {
 printf("Handle 0x00"); 
}

InterruptManager::~InterruptManager()
{
}


void InterruptManager::Activate()
{
  printf("\nStart activate\n");
  asm("sti");
  printf("Done activate\n");
}

uint32_t InterruptManager::HandleInterrupt(uint8_t interrupt, uint32_t esp)
{
  printf("start handle interrupt");
  //const char* debugString = " INTERRUPT";
  char* foo = "INTERRUPT 0x00";
  char* hex = "0123456789ABCDEF";

  foo[12] = hex[(interrupt >> 4) & 0xF];
  foo[13] = hex[interrupt & 0xF];
  printf(foo);

  return esp;
}
\ifndef\uu中断
#定义中断
#包括“types.h”
#包括“port.h”
#包括“gdt.h”
类中断管理器{
公众:
中断管理器(全局可描述*gdt);
~InterruptManager();
静态空洞激活();
静态uint32手动中断(uint8中断号,uint32 esp);
静态空区中断GNORE();
静态void HandleInterruptRequest();
静态void HandleInterruptRequest0x00();
静态void HandleInterruptRequest0x01();
受保护的:
结构网关描述符{
uint16_t handlerAddressLowBits;
uint16_t gdt_代码段选择器;
uint8_t保留;
uint8访问权;
uint16_t handlerAddressHighBits;
}_uuu属性_uuu((压缩));
静态网关描述符可中断描述符[256];
结构中断描述符TablePointer
{
uint16_t尺寸;
uint32_t基地;
}_uuu属性_uuu((压缩));
静态无效SetInterruptDescriptorTableEntry(
uint8_t中断号,
uint16\u t代码段选择器偏移,
void(*handler)(),
uint8_t描述符优先级,
uint8_t描述符类型);
Port8BitSlow PICMASTER命令;
端口8比特流picMasterData;
端口8比特流微微工作命令;
端口8比特流微微工作数据;
};
#恩迪夫
(v2_ordergroove-py27)~/s/wyoos❯❯❯ cat中断.cpp
#包括“interrupts.h”
void printf(常量字符*str);
InterruptManager::GateDescriptor InterruptManager::interruptDescriptorTable[256];
void InterruptManager::SetInterruptDescriptorTableEntry(
uint8_t中断号,
uint16\u t代码段选择器偏移,
void(*handler)(),
uint8_t描述符优先级,
uint8_t描述符类型)
{
printf(“\nGDT条目开始\n”);
InterruptDescriptable[interruptNumber]。handlerAddressLowBits=((uint32_t)处理程序)和0xFFFF;
InterruptDescriptor可[interruptNumber]。handlerAddressHighBits=((uint32_t)处理程序)>>16)和0xFFFF;
InterruptDescriptor可[interruptNumber].gdt_codeSegmentSelector=codeSegmentSelectorOffset;
const uint8_t IDT_DESC_PRESENT=0x00;
interruptDescriptorTable[interruptNumber]。访问权限=IDT_DESC|u PRESENT |描述符类型|(描述符优先级代码段选择器();
常数8\u t IDT\u中断门=0xE;
对于(uint16_t i=0;i<256;i++){
SetInterruptDescriptorTableEntry(i、代码段和中断码、0、IDT_中断门);
}
SetInterruptDescriptorTableEntry(0x20,代码段和HandleInterruptRequest0x00,0,IDT_中断门);
SetInterruptDescriptorTableEntry(0x21,代码段和HandleInterruptRequest0x01,0,IDT_中断门);
picMasterCommand.Write(0x11);
picWorkerCommand.Write(0x11);
picMasterData.Write(0x20);
picWorkerData.Write(0x20);
picMasterData.Write(0x04);
picWorkerData.Write(0x02);
picMasterData.Write(0x01);
picWorkerData.Write(0x01);
picMasterData.Write(0x00);
picWorkerData.Write(0x00);
中断描述符指针idt;
idt.size=256*sizeof(网关描述符)-1;
idt.base=(uint32_t)可中断描述符;
asm易失性(“lidt%0”:“m”(idt));
}
void InterruptManager::interruptgnore(){
}
void InterruptManager::HandleInterruptRequest0x01(){
printf(“句柄0x01”);
}
void InterruptManager::HandleInterruptRequest0x00(){
printf(“句柄0x00”);
}
中断管理器::~InterruptManager()
{
}
void InterruptManager::Activate()
{
printf(“\n启动激活\n”);
asm(“sti”);
printf(“完成激活\n”);
}
uint32\u t中断管理器::手动中断(uint8\u t中断,uint32\u t esp)
{
printf(“启动句柄中断”);
//const char*debugString=“中断”;
char*foo=“中断0x00”;
char*hex=“0123456789ABCDEF”;
foo[12]=hex[(中断>>4)&0xF];
foo[13]=hex[interrupt&0xF];
printf(foo);
返回esp;
}

我的完整源代码可以在

上找到,我有一些建议:1)你应该为所有向量设置一个合适的处理程序。大多数向量都会被发送到InterruptGnore,它不会打印消息,甚至不会执行iret,因此如果它到达那里,它肯定会在没有警告的情况下崩溃。如果你至少把一个消息放入中断,你可以看到它是否到达那里。2)看起来有两种不同的中断管理器实现::HoeLeDebug TrxQuest0x00,一个在汇编,一个在C++。在汇编中写的是正确的,但是用C++编写的一个是被放入中断表中的。3)我没有检查代码的细节来填入IDT。我建议在设置IDT后转储它的原始字节,以确保它以您期望的方式填充。(你不必把整件事都转储掉,只需选择几个条目就足够了。)快速浏览一下。将默认中断处理程序设置为<代码>和中断/代码>,但这是一个C++函数,它是一个规则函数,它可以执行<代码> ReT <代码>结束。你需要做一个
iret
的东西。您可以在中断存根程序集文件中放入这样一个函数。这一行是错误的
const uint8\t IDT\u DESC\u PRESENT=0x00。它应该是
const uint8\u t IDT\u DESC_