【发布时间】:2020-02-02 11:25:16
【问题描述】:
我不明白.code16 或其他.code* 指令的实际用法。我从this question on StackOverflow 的答案中了解到的,
当有人在他们的汇编代码中定义 .code16 并执行以下操作时:
$ gcc -c -m32 -o main.o main.s
它会忽略.code16,并且输出程序集将在 32 位平台上运行。如果有人没有指定 -m 标志,它似乎将配置为 gcc 的标志作为默认值,具体取决于主机。因此,总而言之,.code* 指令总是被-m 标志忽略并取代。
如果我的理解有误,有人可以纠正我吗?在什么情况下我会使用.code16,因为我总是可以定义使用-m16和.code*无论如何都会被忽略,具体取决于目标模式。
.code16(或其他)是否仅在数据无法放入 16 位寄存器时抛出错误,否则它们将保持休眠状态?
【问题讨论】:
-
不,它不会忽略
.code16。它将默认操作数和地址大小设置为 16 位。它生成旨在以 16 位模式运行的代码。它恰好被填充到 32 位 ELF 二进制文件中。 -
@Jester:谢谢。当您说“旨在以 16 位模式运行的代码”时,这到底是什么意思?我无法通过 objdump 确认它,因为它根据传递的
-M标志解析 ELF。因此,它会为相同的 ELF 生成不同的结果,例如如果-M在解析时定义为 32 位而不是 16 位,%ax将更改为%eax。 -
另外
-m16仅对gcc生成的代码有效,如果您有自己的手写程序集则无效。 -
表示默认操作数和地址大小为 16 位。机器码中有前缀
0x66和0x67切换到其他模式。在 16 位代码中,您不需要 16 位的前缀,但您需要 32 位的前缀。在 32 位模式下,情况正好相反。汇编器需要知道您将在哪种模式下运行,因此它可以生成适当的前缀。 16 位模式下的mov $42, %ax为b8 2a 00,32 位模式下同样为66 b8 2a 00。 -
是的,
-M标志到objdump基本上模拟了 cpu 将如何看到指令。所以你可以用它来测试如果你试图在错误的模式下运行代码会发生什么。
标签: assembly x86 linker gnu gnu-assembler