x86除法异常-返回地址

2023-12-14

当尝试在 x86 程序集中为引导加载程序编写一些例程时,我遇到了一个错误,当发生除法错误时,程序将陷入无限循环。通过调查,我发现调用 int 0 会正常通过异常处理程序,然后继续执行程序的其余部分。我自己为 x86 编写了异常处理程序,发生除法错误异常时的返回地址是指令的地址,这意味着它将永远循环执行除法。这是正常行为还是 Virtualbox/我的 cpu 特有的错误?

org 0x7c00      ;put all label addresses at offset 0x7c00

xor ax, ax      ;set up all segment registers
mov ds, ax
mov ax, 0x9000
mov ss, ax
mov sp, 0x1000
mov ax, 0xB800  ;video text memory starts at this address
mov es, ax

mov ah, 0x00
mov al, 0x02
int 0x10        ;go into 80x25 monochrome text

mov [0x0000], word DivideException
mov [0x0002], word 0x0000

xor di, di
xor bx, bx

;int 0   ;this and the divide CX below will cause a division error exception

mov ax, 0
mov cx, 0 ;when exception is handled it prints out
div cx    ;"a divide by zero error happened 0000:7C2D 0000:7C2F
          ;the first address is the division instruction and the second one is 2 bytes after
          ;when int 0 is uncommented out then it will have the two same addresses
jmp $

ToHex:
push bp
mov bp, sp
push bx

mov ax, word [bp+6]
mov bx, word [bp+4]
add bx, 3
mov cx, 16

.Loop:
xor dx, dx
div cx
add dx, 48
cmp dx, 58
jb .Skip
add dx, 7
.Skip:
mov byte [bx], dl
dec bx
cmp ax, 0
jne .Loop

.Ret:
pop bx
mov sp, bp
pop bp
ret

PrintStr:
push bp
mov bp, sp
push bx

mov bx, word [bp+6]
mov ah, byte [bx]
mov bx, word [bp+4]

.PrintLoop:
mov al, byte [bx]

mov word [es:di], ax
inc di
inc di
inc bx
cmp byte [bx], 0x00
jne .PrintLoop

pop bx
mov sp, bp
pop bp
ret

DivideException:
push bp
mov bp, sp
push bx

push word ColorAttributes1
push word String3
call PrintStr
add sp, 4

push word [bp+4]
push word String1
call ToHex
add sp, 4

push word [bp+2]
push word String2
call ToHex
add sp, 4

push word ColorAttributes1
push word String1
call PrintStr

push ds
mov ds, word [bp+4]
mov bx, word [bp+2]

cmp byte [ds:bx], 0xF7  ;checks if theres a 0xF7 byte at the return address
jne .DontAdd            ;for some reason the return address when calling int 0
add word [bp+2], 2      ;directly is the address after the instruction while
.DontAdd:               ;causing a divide error exception through divsion will
pop ds                  ;put the return address at the division leading to an
                        ;infinite loop
push word [bp+4]
push word String1
call ToHex
add sp, 4

push word [bp+2]
push word String2
call ToHex
add sp, 4

push word ColorAttributes1
push word String1
call PrintStr

add sp, 4

pop bx
mov sp, bp
pop bp
iret



String1: db "0000:";, 0x00
String2: db "0000 ", 0x00
String3: db "a divide by zero error happened ", 0x00
ColorAttributes1: db 0x0F ; first nibble is backround color
                         ;second nibble is foreground


times 2048-2- ($-$$) db 0  ;fills the rest with 0's until 510 bytes
dw 0xAA55               ;magic boot sector number

原来8086/8088呢 push 以下指令的地址 for #DE例外情况。
但所有其他 x86 CPU 都会推送故障的起始地址div/idiv操作说明。(至少从 386 开始;但 286 很可能与 386 相同。)

一般来说,这对于 x86 来说是正常的:出错指令会推送出错指令的地址。 x86 机器代码无法可靠/明确地向后解码,因此设计意图是异常处理程序可以检查情况并可能修复它,并重新运行错误指令。

See Intel x86 - 中断服务例程责任它分解了Faults、Traps和Aborts之间的区别,甚至特别提到了之间的区别int 0和一个断层div.

不过,这对于 #PF 页面错误很有用不那么现实对于诸如 FP 和整数算术异常之类的事情。但如果不修复,那么至少报告出现故障的实际指令。例如idiv dword [fs: rdi + 0xf1f7f1f7]向后拆卸会产生歧义。这f7 f1disp32 中的字节是编码div ecx。你也不知道跳跃是否直接跳到了idivFS 前缀后的操作码。因此,获取错误指令开始的实际地址(而不是结束地址)对于调试和可能的其他目的绝对有用。

int 0当然,(如果 IDT 允许,如果您不在实模式下)会推送以下指令的 CS:[ER]IP,因为在修复情况后它无法重新运行而不会出现故障。int一般来说,目的是像这样工作call就返回到指令而言。


8086 的行为似乎是一个有意的决定,旨在以更糟糕的行为为代价来简化硬件。它对最大指令长度没有限制,并且完全避免记住 CPU 内任何位置的指令开始(Ken Shirriff 在回答中引用了一项 Intel 专利)8086 中的中断、指令指针和指令队列).

If cs rep movsb被外部中断中断,中断返回地址在final前缀,而不是实际的指令开始。 (即它将恢复为rep movsb没有cs前缀,如果您按此顺序放置前缀,这将是一场灾难。这是最大的“更糟糕的行为”;你可以通过放置来解决它rep cs movsb由于 8086 没有任何类型的页面错误或可配置的段限制,因此它不能在rep cs movsb或其他rep-string指令,仅异步外部中断。

See 为什么调用和跳转指令使用相对于下一条指令的位移,而不是当前指令的位移?有关 8086 设计决策的更多猜测。

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

x86除法异常-返回地址 的相关文章

随机推荐

  • Windows 窗体 PictureBox - 如何在窗体的特定区域中显示图像

    我使用以下代码在我的表单之一中打开并显示图像fileDialog private void btnExplorer Click object sender EventArgs e OpenFileDialog openFileDialog1
  • C++ 中的 include 与 python 中的导入

    python中的 import 相当于c 中的 include 吗 我可以像处理 Python 模块名称一样考虑 C 中的命名空间吗 include在 C 和 C 中是文本包含 import在Python中是very不同 根本没有文字包含
  • 使用 localStorage 缓存 Kendo UI DataSource 对象

    我正在将 Kendo UI ComboBox 与外部 XML 数据源一起使用 这是数据源代码 try var csDataSrc new kendo data DataSource transport read Data StateList
  • 处理现有记录时的 django 表单和 ModelMultipleChoiceField

    我正在尝试做一些我认为很常见的事情 但我真的不确定如何解决这个问题 我目前所做的 目前 我在表单上生成了一个复选框列表 使用 CheckboxSelectMultiple 该列表自动勾选 django 中所有用户列表中 成员 中的所有用户
  • JCombobox - 仅在值更改时执行动作侦听器

    我有一个JComboBox 并且我有一个附加的监听器 现在 每次用户从下拉列表中 选择 某些内容时 事件都会触发 即使他们只是重新选择了之前选择的值 如果组合框的选定值与选择之前不同 是否有任何方法可以仅触发事件 我想我可以将组合框的值存储
  • 在java程序中创建暂停或等待效果

    我正在用 Java 编写一个简单的钓鱼模拟器游戏 我希望每次施法后都有一个随机生成的等待时间 当等待结束时 会发生随机事件 一条鱼会被捕获 一条鱼会咬住你的鱼饵 等等 我听说过很多关于 Thread sleep 的坏事 并且想知道在这种情况
  • JAXB - 将动态生成的名称空间移动到文档根目录

    我有这个 POJO 封装了 Atom 条目的动态非嵌套元素 public class SimpleElement private Namespace namespace private String tagName private Stri
  • 如何在 Eclipse Swing 项目中使用 JavaFX

    我想在 Swing 应用程序中使用一些 JavaFX 组件 尤其是 JFXPanel 因为它支持 HTML 5 渲染 我的应用程序当前在 Eclipse 4 3 Kepler 中设置 并且我的计算机上安装了最新的 Java 7 JDK 本教
  • 在 Google Chrome 扩展程序中使用 Stripe 信用卡表单 - 无法避免“付款不安全?”

    我正在尝试在浏览器弹出窗口中获取一个简单的 Stripe 信用卡表单 以用于 google chrome 扩展 然而 在最新版本的 Chrome 中 信用卡表单始终附有 付款不安全 的消息 付款不安全 我已经在这里阅读了 google ch
  • Python 中的统计累加器

    统计累加器允许执行增量计算 例如 为了计算在任意时间给出的数字流的算术平均值 可以创建一个对象来跟踪当前给出的项目数 n以及它们的总和 sum 当一个人请求平均值时 该对象只是返回sum n 像这样的累加器允许您增量计算 即当给定新数字时
  • 可扩展字符串错误

    我试图在警报对话框中显示一些文本作为超链接 该过程的一部分要求我使用 SpannableString 来格式化一些文本 问题是我的应用程序在代码的 SpannableString 部分遇到运行时错误 TextView Tv TextView
  • 返回承诺时自定义异步验证不起作用

    我正在调用 Web api 来检查 urlalias 是否可用 对于此任务 我在异步验证器中使用 httpservice 问题是 当调用验证器时 将执行所有正确的代码路径 所有console log 运行并按预期运行 验证的承诺是否返回 解
  • 将 calendar_date_select 与 Rails 3 结合使用

    我一直在尝试在注册过程中创建用户出生日期选择字段 代码如下所示 div h3 Register h3 div style width 374px margin 0 auto div div div div div div
  • 在处理传入请求之前,如何在“TISAPIApplication”中建立 ADO 数据库连接?

    TADOConnectionDelphi ISAPI 应用程序的应用程序初始化部分无法连接 TISAPIApplication 应用程序是使用 Delphi XE SPI 构建的 运行 Win 7 64 IIS 7 5 和 WinServe
  • Excel VBA:具有不同文件扩展名的 SaveCopyAs

    我有一个扩展名为 xlsb 的 Excel 文件 并使用其宏根据内容生成其他几个 Excel 工作表 宏的工作方式是更改原始 Excel 文件 然后使用SaveCopyAs方法保存生成的 Excel 工作表 生成的 Excel 工作表应以
  • 发布时如何设置ASPNETCORE_ENVIRONMENT?

    我有几个 WebDeploy 发布配置文件 可将我的 NET Core Web 项目部署到各个位置 开发 QA IIS 上的阶段 为了让应用程序知道它在哪里运行 我需要设置 ASPNETCORE ENVIRONMENT 环境变量 是否可以在
  • 来自特定麦克风的 Web Audio Api 输入

    我正在使用 Web Audio Api navigator getUserMedia audio true function function 进行音频录制 如果用户有多个麦克风设备 我可以选择所需的录音设备吗 我遇到过一个有问题的情况 一
  • 在 sed 中使用美元符号进行变量替换和字符

    我尝试使用 sed 更改名为 fusion gnu 的文件中的一行 我有一个名为lafila 这是一个文件名 目前 我可以这样做 lafila nGas060 dat sed i 6s plot lafila using 1 2 with
  • 即时应用程序模块在另一个非基本模块中搜索资源

    我正在开发一个即时应用程序 它有base模块和 2 个功能模块 feature1 and feature2 当我尝试启动时遇到奇怪的崩溃feature2活动 java lang RuntimeException Unable to star
  • x86除法异常-返回地址

    当尝试在 x86 程序集中为引导加载程序编写一些例程时 我遇到了一个错误 当发生除法错误时 程序将陷入无限循环 通过调查 我发现调用 int 0 会正常通过异常处理程序 然后继续执行程序的其余部分 我自己为 x86 编写了异常处理程序 发生