Intel x86 - 中断服务例程责任

2024-01-18

我没有真正意义上的问题,但我会尽力澄清内容问题。假设我们有一个微内核(PC Intel x86;32 位保护模式)中断描述符表 (IDT) and 中断服务程序 (ISR)对于每个CPU异常。 ISR 被成功调用,例如Division by Zero例外。

global ir0
extern isr_handler

isr0:

    cli
    push 0x00   ; Dummy error code
    push %1     ; Interrupt number

    jmp isr_exc_handler

isr_exc_handler:

; Save the current processor state

    pusha

    mov ax, ds
    push eax

    mov ax, 0x10 ; Load kernel data segment descriptor
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ; Push current stack pointer

    mov eax, esp
    push eax

    call isr_handler ; Additional C/C++ handler function

    pop eax     ; Remove pushed stack pointer

    pop ebx     ; Restore original data segment descriptor
    mov ds, bx
    mov es, bx
    mov fs, bx
    mov gs, bx

    popa

    add esp, 0x08 ; Clean up pushed error code and ISR number
    sti

    iret

问题是中断一次又一次地抛出。结果,ISR 被一次又一次地调用。通过反复试验,我发现引发异常的行,int x = 5 / 0,在循环中执行,因此指令指针(EIP) 不增加.

当我手动增加推送到堆栈的 IP 值时,会发生预期的行为。 CPU 然后执行恶意代码行之后的下一条指令。当然,在 ISR 被调用一次之后。

对于我的实际问题:ISR 是否有必要增加 IP?或者这是“CPU/硬件”的责任?继续前进的正确行为是什么?


您有责任了解处理器如何以及为何调用中断服务例程,并相应地为 ISR 编写代码。您试图将由除零错误生成的异常视为由硬件中断生成。然而,这不是 Intel x86 处理器处理此类异常的方式。

x86处理器如何处理中断和异常

有几种不同类型的事件将导致处理器调用中断向量表中给出的中断服务例程。这些统称为中断和异常,处理器可以通过三种不同的方式处理中断或异常:fault, as a trap,或作为abort。除法指令会生成除法错误 (#DE) 异常,该异常将作为错误进行处理。硬件和软件中断作为陷阱进行处理,而其他类型的异常则作为这三种方式之一进行处理,具体取决于异常的来源。

Faults

如果异常的性质允许以某种方式纠正,则处理器将异常作为错误来处理。因此,压入堆栈的返回地址指向生成异常的指令,因此故障处理程序知道导致故障的具体指令,并可以在解决问题后恢复执行故障指令。页面错误 (#PF) 异常就是一个很好的例子。它可用于通过让故障处理程序为故障指令尝试访问的地址提供有效的虚拟映射来实现虚拟内存。有了有效的页面映射,指令就可以恢复并执行,而不会生成另一个页面错误。

Traps

中断和某些类型的异常(所有这些都是软件异常)都作为陷阱进行处理。陷阱并不意味着指令执行过程中出现错误。硬件中断发生在指令执行之间,软件中断和某些软件异常有效地模仿了这种行为。陷阱是通过推送正常执行的下一条指令的地址来处理的。这允许陷阱处理程序恢复被中断代码的正常执行。

Aborts

严重且不可恢复的错误将作为中止处理。只有两种异常会生成中止:机器检查 (#MC) 异常和双重故障 (#DF)。机器检查指令是检测到处理器本身硬件故障的结果,无法修复,并且无法可靠地恢复正常执行。当处理中断或异常期间发生异常时,就会发生双故障异常。这使得 CPU 处于不一致的状态,处于调用 ISR 的所有必要步骤中间的某个位置,并且无法恢复。压入堆栈的返回值可能与导致中止的原因有任何关系,也可能没有任何关系。

通常如何处理除法错误异常

通常,大多数操作系统通过将除法错误异常传递给正在执行的进程中的处理程序来处理,或者通过终止进程来处理失败,表明它已经崩溃。例如,大多数 Unix 系统向进程发送 SIGFPE 信号,而 Windows 使用其结构化异常处理机制执行类似的操作。这样进程的编程语言运行时就可以设置自己的处理程序来实现所使用的编程语言所需的任何行为。由于除以零会导致 C 和 C++ 中的未定义行为,因此崩溃是可以接受的行为,因此这些语言通常不会安装除以零处理程序。

请注意,虽然您可以通过“递增 EIP”来处理除法错误异常,但这比您想象的要困难,并且不会产生非常有用的结果。您不能只向 EIP 添加一个或某个其他常量值,您需要跳过整个指令,该指令的长度可能在 2 到 15 个字节之间。有三种指令可能导致此异常:AAM、DIV 和 IDIV,并且可以使用各种前缀和操作数字节对这些指令进行编码。您需要对指令进行解码才能弄清楚它有多长。执行此增量的结果将如同该指令从未执行过一样。错误指令不会计算出有意义的值,并且您将无法知道程序为何无法正确运行。

阅读文档

如果您正在编写自己的操作系统,那么您需要提供英特尔软件开发人员手册,以便您可以经常查阅。特别是,您需要阅读和学习第 3 卷:系统编程指南中的几乎所有内容,不包括虚拟机扩展章节和后面的所有内容。那里详细介绍了您需要了解的有关如何中断和异常的所有内容,以及您需要了解的许多其他内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Intel x86 - 中断服务例程责任 的相关文章

  • ARM 调用约定是否允许函数不将 LR 存储到堆栈中?

    正如标题所示 我在理解 ARM 架构的调用约定时遇到问题 特别是 我仍然很难知道当你调用子程序时 LR 寄存器会发生什么 我认为 当您进入子程序时 处理 LR 寄存器的最明显 最安全的方法是将其存储到堆栈中 但该行为没有出现在文档中 因此我
  • 装配中出现奇怪的字符?

    我写了以下代码 386 model small stack 100h data text db Paper 0 code start lea dx text mov ah 9h int 21h mov ah 4ch int 21h end
  • 汇编中如何计算负数

    我是汇编新手 我有一个关于如何表示负数的问题 我有三个 DWORDS 变量 比方说 result DWORD 0 i DWORD 3 j DWORD 5 我想计算这个公式 结果 i j 8 但是 当我执行 i j 时 由于符号 结果将是一个
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • 一条指令可以同时处于两种寻址模式吗?

    我在书中读到了以下内容从头开始编程 处理器有多种不同的访问数据的方式 称为 寻址模式 最简单的模式是立即模式 其中 要访问的数据嵌入在指令本身中 例如 如果我们想将寄存器初始化为 0 而不是给出 计算机要从中读取 0 的地址 我们将指定立即
  • 预取双类成员需要转换为 char*?

    我有一个正在使用的课程 mm prefetch 预先请求包含 double 类型的类成员的缓存行 class MyClass double getDouble return dbl other members double dbl othe
  • C++ 中的 CPUID 实现

    我想知道这里是否有人有一些可以从任何托管 net 语言引用的 C CPUID 实现的好示例 另外 如果情况并非如此 我是否应该注意 X86 和 X64 之间的某些实现差异 我想使用 CPUID 来获取运行我的软件的机器上的信息 崩溃报告等
  • 在 x86 程序集中将整数打印到控制台

    当我在 16 位汇编中添加两个值时 将结果打印到控制台的最佳方法是什么 目前我有这个代码 CODE START mov ax 1 put 1 into ax add ax 2 add 2 to ax current value mov ah
  • 汇编-符号标志和奇偶校验标志

    我不明白什么时候设置标志标志 什么时候设置奇偶校验 据我所知 符号标志表示运算结果的符号 0表示正数 1表示负数 那么为什么在下一个代码中 mov al 5 sub al 124 SF为零 结果是负数 关于PF 为什么a和b中设置了PF a
  • 取消的分支与常规分支有何不同?

    特别是对于 SPARC Assembly 取消的分支与常规分支有何不同 我一直认为 当我需要填充分支指令的 nop 延迟槽时 需要取消分支指令 但是 我认为我在这一部分上是不正确的 因为您可以在不取消分支的情况下填充 nop 如果不采用分支
  • 为什么不能执行 mov [eax], [ebx] [重复]

    这个问题在这里已经有答案了 我可以做这个 mov eax ebx 和这个 mov eax ebx 甚至这个 mov eax ebx 但不是这个 错误C2415 mov eax ebx 只是wtf 为什么 它与 ptr1 ptr2 相同 为什
  • 为什么 Solaris 汇编器生成的机器代码与 GNU 汇编器在这里不同?

    我为 amd64 编写了这个小汇编文件 对于这个问题来说 代码的作用并不重要 globl fib fib mov edi ecx xor eax eax jrcxz 1f lea 1 rax ebx 0 add rbx rax xchg r
  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 近调用/跳转表并不总是在引导加载程序中工作

    一般问题 我一直在开发一个简单的引导加载程序 并在某些环境中偶然发现了一个问题 在这些环境中 此类指令不起作用 mov si call tbl SI Call table pointer call call tbl Call print c
  • 在 x86-64 CPU 上通过交叉修改代码重现意外行为

    Question 对于可能在 x86 或 x86 x64 系统上触发意外行为的交叉修改代码有哪些想法 在这些系统中 交叉修改代码中的所有操作均已正确完成 但在执行处理器之前执行序列化指令除外修改代码 如下所述 我有一个 Core 2 Duo
  • 在 x86 ASM 中测试零通常哪个更快:“TEST EAX, EAX”与“TEST AL, AL”?

    测试 AL 中的字节是否为零 非零通常哪个更快 TEST EAX EAX TEST AL AL 假设之前有一个 MOVZX EAX BYTE PTR ESP 4 指令加载了一个带有零扩展的字节参数到 EAX 的其余部分 防止了我已经知道的组
  • C# 是否可以中断 ThreadPool 内的特定线程?

    假设我已将一个工作项排入队列ThreadPool 但是如果没有要处理的数据 从BlockingQueue 如果队列为空并且队列中不再有工作 那么我必须调用Thread Interrupt方法 如果我想中断阻塞任务 但是如何用 a 做同样的事
  • 为什么当大小大于 50 时,该程序花费的时间会呈指数级增长?

    所以我正在为类编写一个 ARM 汇编快速排序方法 我对大部分内容都有了解 除了复杂性没有意义 我们将其与我们制作的另一种冒泡排序方法进行比较 它对于具有 1 个参数和 10 个参数的示例表现更好 然而 我什至无法比较 100 个参数测试 因
  • 使用 Easy 68K (68000) 组装范围内的随机数

    我正在使用 Easy 68K 模拟器创建一个简单的黑杰克游戏 需要使用随机数来分配牌 我的牌必须在 2 到 11 的范围内 我似乎每次都得到相同的数字 但它不在我预期的范围内 我的卡值需要以 D3 结束 因此我有以下随机数代码 CLR L
  • “rep stos”x86 汇编指令序列有什么作用?

    我最近偶然发现了以下汇编指令序列 rep stos dword ptr edi For ecx重复 存储内容eax到哪里edi指向 递增或递减edi 取决于方向标志 每次 4 个字节 通常 这用于memset型操作 通常 该指令简单地写成r

随机推荐

  • 什么是金融运作中的锁定、僵局问题?

    盘问SQL 什么时候应该使用 with nolock https stackoverflow com questions 686724 sql when should you use with nolock 在一家当地的金融机构 我因为向他
  • 记录清单

    以下代码似乎向列表中添加了一条新记录 但会用最后创建的记录覆盖所有记录 我可以让它正常工作 lpr Add new personRecord Age pr Age Name pr Name 但这似乎更冗长 并且在真正的应用程序中记录要大得多
  • 使用 Springfox 在 Spring 应用程序中记录 jax-rs 服务

    我想使用 Springfox 记录现有应用程序的 API 我将这些依赖项添加到 pom xml 中
  • 反编译的Jar文件的类路径

    所以我不是计算机科学专业或任何其他专业 我只是在研究一些东西来练习我从视频中观看的一些 Java 技能 我知道这不是主要的方法 但请让我这样做 所以我提取了一个 jar 文件 http www zenlunatics com quizcar
  • C# Linq 与柯里化

    我正在玩一点函数式编程及其各种概念 所有这些东西都很有趣 我曾多次阅读过有关柯里化的内容以及它的优势 但我不明白这一点 以下源代码演示了柯里化概念的使用以及 linq 的解决方案 实际上 我没有看到使用柯里化概念的任何优点 那么 使用柯里化
  • 在 C# 中将结构体指针作为参数传递

    我有一个 C 函数 已导出到 DLL I 包含一个结构体指针作为参数之一 我需要在 C 中使用此函数 因此我使用 DLLImport 作为该函数 并使用 StructLayout 在 C 中重新创建了该结构 我尝试使用 ref 传入参数 并
  • Prisma2:如何用 Paljs 解决 n+1 问题

    感谢您的帮助 我在前端使用阿波罗客户端 在后端使用graphql nexus https nexusjs org docs prisma2 和 graphql yoga 服务器 我想用 paljs plugins 解决n 1 问题 在前端我
  • 自动映射器 - 将对象与集合映射

    使用自动映射器 我需要映射以下类的对象 public class RemoteClass public IEnumerable
  • 如何处理“有符号/无符号不匹配”警告 (C4018)?

    我使用大量编写的计算代码c questions tagged c 2b 2b考虑到高性能和低内存开销 它使用STL容器 主要是std vector 很多 并且几乎在每个函数中迭代该容器 迭代代码如下所示 for int i 0 i lt t
  • 这是使用 thenFetch() 加载多个集合的正确方法吗?

    我正在尝试使用急切地加载所有集合NHibernate 3 阿尔法 1 http nhforge org media p 690 aspx 我想知道这是否是使用 thenFetch 的正确方法 具有复数名称的属性是集合 其他的只是一个单一的对
  • Django 如何使用 django.contrib.auth 添加注销成功消息?

    我没有使用all auth 我正在使用标准身份验证系统和 url 提供的django contrib auth 我还确保注销时用户会自动重定向到登录页面 LOGOUT REDIRECT URL login 我想添加一条消息 以便用户知道他们
  • IntelliJ 检查给出“无法解析符号”,但仍编译代码

    平台 IntelliJ社区版10 0 3SDK jdk1 6 0 21操作系统 Windows 7 所以我在使用 IntelliJ 时遇到了一个奇怪的情况 这让我完全陷入困境 我设置了一个 Maven 项目 并将 log4j 添加为 pom
  • 尝试使用selenium截屏时出现空指针异常[重复]

    这个问题在这里已经有答案了 我编写了一个Java类 它使用selenium webdriver来快速浏览网站并测试各种功能 我还编写了一个单独的类 它将用于执行 takeScreenshot 方法 一旦测试命中执行截图方法的代码 浏览器就会
  • 无法创建推力装置矢量

    所以我尝试开始 GPU 编程并使用 Thrust 库来简化事情 我创建了一个测试程序来使用它并查看它是如何工作的 但是每当我尝试创建具有非零大小的推力 device vector时 程序就会崩溃并显示 运行时检查失败 3 变量 结果 正在使
  • 汇编vim语法高亮

    默认的程序集语法文件不能很好地工作 在网上搜索有关 Gas 程序集的信息时 我没有找到任何有关 vim 的 Gas AT T 语法文件的信息 有人发现这个吗 我无法编写自己的语法文件 http img168 imageshack us im
  • 如何在R中将时间格式转换为数字

    示例如下所示 A tibble 10 x 3 trip id start time end time
  • SonarQube 在代码分析中忽略 getter/setter

    SonarQube 仪表板中是否有允许忽略 getter 和 setter 的设置 这听起来是一个比在代码库中的每个方法上编码 nopmd 更好的选择 我的代码库有很多这样的东西 它们极大地降低了 Sonarqube 仪表板中报告的单元测试
  • 更改 Electron 中可拖动区域上的光标

    我正在 Electron 中制作一个应用程序 我有一个无框窗口 我有一些顶部区域 webkit app region drag但当我这样做时 不会改变 显然它在这个片段中是不可拖动的 因为它不是一个电子应用程序 但基本上光标在可拖动的元素上
  • 使用matlab配色方案将float转换为RGB

    例如 如果我有一个浮动0 568 浮动保证是0 gt 1 有没有办法将其转换为 RGB 值 双精度 1 0 1 0 1 0 or int 255 255 255 在当前的 matlab 配色方案 即正常 热 HSV 等 下 你可以试试这个
  • Intel x86 - 中断服务例程责任

    我没有真正意义上的问题 但我会尽力澄清内容问题 假设我们有一个微内核 PC Intel x86 32 位保护模式 中断描述符表 IDT and 中断服务程序 ISR 对于每个CPU异常 ISR 被成功调用 例如Division by Zer