要使用 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
表示,
Enables assembly of nonprivileged instructions for the Pentium Pro processor. (32-bit MASM only.)
为什么在 64 位模式下不是这样?
最佳答案
32 位 MASM 可以根据指令在 16 位和 32 位可执行文件之间进行选择。构建 64 位代码时情况并非如此,因此相关指令较少。
x86-64 ISA 保证支持 PPro 指令,因此无需启用它们。 (与 SSE/SSE2 相同)。您的代码以 64 位模式运行的事实意味着它们可用,就像 .model flat
中的 movzx
等 386 功能一样。 但是您在 MASM 中使用命令行选项而不是指令来选择。
MASM 是否没有针对其他后续扩展的指令,例如 .haswell
或 .bmi2
来帮助您避免意外使用较新的指令,例如 AVX2 vpermpd ymm0, ymm1, 0x01
当你只想使用 AVX1 时?其他一些汇编器确实具有类似的功能,例如 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 字节小堆栈。
关于visual-studio - 32 位 MASM 模式与 64 位有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65279900/