32 位 MASM 模式与 64 位有何不同?
Posted
技术标签:
【中文标题】32 位 MASM 模式与 64 位有何不同?【英文标题】:How does 32-bit MASM mode differ from 64-bit? 【发布时间】:2021-03-24 13:18:18 【问题描述】:要使用 MASM 用 32 位汇编语言编写完整的程序,可以这样开始,
.686
.model flat,c
.stack 100h
.data
number sdword 5
.code
main proc
mov eax,number
ret
main endp
end main
而在 64 位模式下,代码编写为
.data
number sdword 5
.code
main proc
mov eax,number
ret
main endp
end
这些设置被设置为默认值,这导致在 64 位模式下组装时出现错误,不是因为平台设置为 Win32,而是默认入口点 mainCRTStartup。要解决此问题,必须在高级链接器选项中将其设置为 main
。
我的问题是,为什么在 32 位模式下不会遇到这样的问题,而 mainCRTStartup 入口点到底指的是什么?我的第二个问题是,为什么在 64 位模式下汇编我们省略了第一条指令行.686 .model flat,c .stack 100h
我们不必分配堆栈以及语言类型吗?
指令.686
表示,
为 Pentium Pro 处理器启用非特权指令的汇编。 (仅限 32 位 MASM。)
为什么在 64 位模式下不是这样?
【问题讨论】:
【参考方案1】:32 位 MASM 可以在 16 位和 32 位可执行文件之间进行选择,具体取决于指令。构建 64 位代码时并非如此,因此相关的指令较少。
x86-64 ISA 保证支持 PPro 指令,因此无需启用它们。 (与 SSE / SSE2 相同)。您的代码在 64 位模式下运行这一事实意味着它们是可用的,就像 .model flat
中的 movzx
等 386 个功能一样。 但您在 MASM 中使用命令行选项而不是指令来选择。
当您只想使用 AVX1 时,MASM 是否没有针对其他后续扩展(如 .haswell
或 .bmi2
)的指令来帮助您避免意外使用新指令(如 AVX2 vpermpd ymm0, ymm1, 0x01
)?其他一些汇编程序确实具有类似的功能,例如 YASM 的 CPU
指令,或者 GNU 汇编程序可以让您限制功能。 (默认情况下,GAS 和 YASM/NASM 接受他们所知道的一切。)
x86-64 长模式也强制使用平面内存模型(CS.base = DS.base = ES.base = SS.base),因此无需选择内存模型。非平面内存分段只能在兼容模式下的 64 位内核下实现(如 32 位或 16 位保护模式的用户空间端)。 https://en.wikipedia.org/wiki/X86-64#Operating_modes
此外,MASM .model
也是假设 32 位模式与 16 位模式的代理,这很奇怪。其他汇编程序将其更正交地分开,例如 bits 16
/ bits 32
/ bits 64
以设置当前模式。 (但在 NASM 中,它不会更改输出文件格式;它只是让您将 64 位代码放入 32 位目标文件中,除非您正在编写一个 切换的内核,否则您不想这样做 模式。)
对于.stack
,主线程堆栈的最大大小由链接器设置(使用/STACK
命令行选项),而不是汇编器。这取代了让汇编器将元数据放在.obj
文件中以供链接器查找的机制,或者它实际上工作的机制。 (AFAIK .stack
无论如何只对 16 位可执行文件很重要,甚至对 .model flat
也不重要。
您通常不希望在 32 位代码中使用 256 字节的微小堆栈)。
【讨论】:
MASM 没有指令 - VS2019 的 masm 指令的 list 说“没有”。它们确实有处理器指令,但它们都被标记为“仅限 32 位”。 声明 x86-64 长模式强制使用平面内存模型,是否也强制不使用任何高级指令,例如.if .else .repeat
等?
@EnthusiastiC x64 MASM 不支持任何“更高级别”指令,例如 .if
、.while
和 INVOKE
。它们需要更新以生成适当的 64 位指令,而微软从不打扰。就像 Peter Cordes 所说的那样,像这样的高级指令违背了编写汇编代码的全部目的。如果您想要一种高级编程语言,那么您应该使用高级编程语言。例如,C 编译器将为其函数调用和 if
和 while
语句生成比 MASM 为 INVOKE
.if
和 .while
生成的更好的代码。
@EnthusiastiC 这是一个单独的问题,这里已经有人问过了:***.com/questions/29390886/…
因此,总而言之,微软没有更新 32 位高级指令以便能够在较新的 64 位版本中实现它们,因为它们毫无意义,因为汇编会浪费.此外,64 位版本与 32 位版本不同,它无法像 .model flat, c
中的 32 位那样指定语言类型。以上是关于32 位 MASM 模式与 64 位有何不同?的主要内容,如果未能解决你的问题,请参考以下文章
32位程序下调用64位函数——进程32位模式与64位模式切换
当我们在 Visual Studio SSIS 项目中点击调试按钮时——它是在 32 位还是 64 位模式下运行——32 位提供程序是不是与 64 位运行模式兼容?