如何强制 NASM 将 int3 编码为 0xCC

Posted

技术标签:

【中文标题】如何强制 NASM 将 int3 编码为 0xCC【英文标题】:How to force NASM to encode int3 as 0xCC 【发布时间】:2018-03-12 07:12:22 【问题描述】:

我正在尝试使用 NASM 组装以下代码

 section .text
 global _start


_start:

mov eax, 1
int 3

Objdump -D 产生:

test:     file format elf64-x86-64


Disassembly of section .text:

0000000000400080 <_start>:
 400080:    b8 01 00 00 00          mov    $0x1,%eax
 400085:    cd 03                   int    $0x3

有趣的是,当用 GAS 组装时,int 3 被编码为 0xCC 而不是 cd 03,这是为什么呢?

【问题讨论】:

请注意one of the reasons MS chose to fill uninitialized memory with 0xCC to aid debugging is because of the int 3 【参考方案1】:

使用int3 助记符进行特殊的单字节编码。

nasm -l /dev/stdout /tmp/foo.asm
 1 00000000 CD03                    int 3
 2 00000002 CC                      int3

来自Intel's insn set manual entry for int

INTOINT3 (CC) 生成的中断与INT n 生成的中断在以下方面有所不同:

在虚拟 8086 模式下不会发生正常的 IOPL 检查。使用任何 IOPL 值进行中断(无故障)。

虚拟 8086 模式扩展 (VME) 启用的中断重定向不会发生。中断始终由保护模式处理程序处理。

这些功能不属于 CD03,即 INT 3 的“正常”2 字节操作码

它还说:

Intel 和 Microsoft 汇编器不会从任何助记符生成 CD03 操作码

因为 2 字节编码没有任何正常/常见的用例。 NASM 保持简单,始终使用CD 操作码作为int 助记符。

当 NASM 确实将 mov rax, 1 优化为 mov eax,1 之类的东西时,它是使用相同助记符的不同操作码。 IDK 如果实施起来不方便,或者 NASM 只是决定不这样做。将int3 视为一条特殊指令,与int n 不同,这是有道理的,因为它只有1 个字节。

【讨论】:

除了向后兼容之外,使用 CD03 的意义何在? @Trey:它们在 vm86 模式下的行为不同。除此之外,可能没有理由输入 int 3 而不是 int3,但 NASM 为您提供了选择。 很遗憾他们没有使用不同的助记符(例如“break”),因此软件中断之间的差异(受权限检查,如果这些检查失败)并且断点异常(不是软件中断并且不受权限检查)更加明显。 @Brendan:在这种情况下,“他们”是英特尔,对吧?是的,同意。 @Brendan - 也许是缺乏远见?指令集最初是在 70 年代设计的。特权级别和保护在 80 年代后期得到了支持。没有多少人期望这会持续到下一个千年。 :-)

以上是关于如何强制 NASM 将 int3 编码为 0xCC的主要内容,如果未能解决你的问题,请参考以下文章

为什么有时候程序出问题会打印出“烫烫烫烫...

int3断点指令的原理和示例

断点之软件断点的一些基本知识(INT3)

探秘INT3指令

探秘INT3指令

常用断点设置