32 位 MASM 模式与 64 位有何不同?

Ent*_*tiC 3 x86 assembly masm 32bit-64bit visual-studio

要使用 MASM 以 32 位汇编语言编写完整的程序,可以这样开始:

.686
.model flat,c
.stack 100h
.data
number sdword 5
.code
main proc
mov eax,number
ret
main endp
end main
Run Code Online (Sandbox Code Playgroud)

而在 64 位模式下,代码写为

.data
number sdword 5
.code
main proc
mov eax,number
ret
main endp
end
Run Code Online (Sandbox Code Playgroud)

这些设置设置为默认值,导致在 64 位模式下编译时出现错误,不是因为平台设置为 Win32,而是因为默认入口点 mainCRTStartup。main要解决此问题,必须在高级链接器选项中将其设置为。

我的问题是,为什么在 32 位模式下不会遇到这样的问题,而 mainCRTStartup 入口点到底指的是什么?我的第二个问题是,为什么在 64 位模式下汇编时我们省略了第一行指令,.686 .model flat,c .stack 100h我们不需要分配堆栈以及语言类型吗?该指令 .686表明,

启用 Pentium Pro 处理器的非特权指令汇编。(仅限 32 位 MASM。)

为什么64位模式下不是这样?

Pet*_*des 5

32 位 MASM 可以根据指令在 16 位和 32 位可执行文件之间进行选择。构建 64 位代码时情况并非如此,因此相关指令较少。

x86-64 ISA 保证支持 PPro 指令,因此无需启用它们。(SSE / SSE2 相同)。事实上,您的代码在 64 位模式下运行意味着它们可用,movzx就像.model flat. 但您可以在 MASM 中使用命令行选项而不是指令来选择

MASM 是否没有针对其他后续扩展的指令,例如.haswell.bmi2来帮助您避免意外使用较新的指令,例如vpermpd ymm0, ymm1, 0x01当您只想使用 AVX1 时使用 AVX2?其他一些汇编器确实具有类似的功能,例如 YASMCPU指令,或者 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//设置当前模式。(但在 NASM 中,这不会改变输出文件格式;它只是让您将 64 位代码放入 32 位目标文件中,除非您正在编写一个切换模式的内核,否则您不想这样做。)bits 32bits 64


对于.stack,主线程堆栈的最大大小由链接器(使用/STACK命令行选项)设置,而不是由汇编器设置。.obj这取代了让汇编器将元数据放入文件中以供链接器查找的机制,或者它实际工作的方式。(无论如何,AFAIK.stack只对 16 位可执行文件有意义,甚至对.model flat.