要使用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
指示
为奔腾Pro处理器启用非特权指令的汇编。(仅限32位MASM。(
为什么在64位模式下不是这样?
32位MASM可以在16位和32位可执行文件之间进行选择,具体取决于指令。构建64位代码时并非如此,因此相关的指令较少。
x86-64 ISA保证支持PPro指令,因此无需启用它们。(SSE/SSE2相同(。事实上,您的代码是在64位模式下运行的,这意味着它们是可用的,就像.model flat
中的386个特性(如movzx
(一样但是您可以通过命令行选项而不是指令来选择,在MASM中。
MASM是否没有针对.haswell
或.bmi2
等其他后续扩展的指令,以帮助您避免意外使用较新的指令,如仅打算使用AVX1的AVX2vpermpd 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字节堆栈(。