Gcc 用g++-march=x86-64是否在32位操作系统上运行?

Gcc 用g++-march=x86-64是否在32位操作系统上运行?,gcc,g++,x86-64,32bit-64bit,Gcc,G++,X86 64,32bit 64bit,我想我混淆了x86-64/i686体系结构和32位/64位操作系统 如果我在32位操作系统(例如Ubuntu 14.04)上使用g++构建应用程序,那么-m64不是有效选项,我无法构建64位二进制文件。但是,g++并不抱怨使用-march=x86-64。(硬件是核心i7。) 然后,如果我构建在64位操作系统(例如Ubuntu 20.04)上,我可以在-m32和-m64之间切换,构建32位或64位二进制文件 所以,我的理解是 -m32和-m64指示可以在哪些操作系统上使用二进制文件。(包括64位操

我想我混淆了x86-64/i686体系结构和32位/64位操作系统

如果我在32位操作系统(例如Ubuntu 14.04)上使用
g++
构建应用程序,那么
-m64
不是有效选项,我无法构建64位二进制文件。但是,
g++
并不抱怨使用
-march=x86-64
。(硬件是核心i7。)

然后,如果我构建在64位操作系统(例如Ubuntu 20.04)上,我可以在
-m32
-m64
之间切换,构建32位或64位二进制文件

所以,我的理解是

-m32
-m64
指示可以在哪些操作系统上使用二进制文件。(包括64位操作系统上使用的32位二进制文件以及相应的库)

-march
定义将用于代码生成的指令集,而不管它将在哪个操作系统上运行

所以我的主要问题是


鉴于我可以使用
-m32-march=x86-64
在32位操作系统上构建和运行二进制文件,这是否意味着x86-64指令可以在32位操作系统上使用?

不,64位指令不能在32位操作系统下使用(甚至在64位内核下的32位用户空间中使用),这不是
-march=x86-64
的意思


-march=x86-64
意味着目标CPU支持x86-64保证的ISA扩展基线集:SSE2、P6功能,如CMOV、CPUID、RDTSC等。但如果没有
-m64
,代码仍将在32位模式下工作

(对于x86-64的目标ISA,它们本身并不是“扩展”。但我们仍然通常说x86-64意味着SSE和SSE2,因为这是一种对在XMM寄存器上运行的指令进行分类的简便方法。如果我们将x86-64本身视为x86的扩展,这是有意义的。)

因此
-march=x86-64
-march=k8
-march=nocona
非常相似(特定于早期的x86-64 CPU)。与这些选项一样,它对
-m32
完全有效,并不意味着生成64位代码。 GCC仍然知道(从
-m32
)它的目标是32位模式(受保护或兼容模式),而不是64位长模式

由于这些模式使用不兼容的机器代码格式,因此与16位到32位的转换完全不同,您可能希望在生成16位代码时使用32位寄存器。在x86-64中,64位寄存器只能在长模式下使用,不能在兼容模式或传统模式(如受保护模式)的任何子模式下使用。看

这里的关键点是,32位进程在compat模式下(在64位内核下)所能做的事情没有在受保护模式下(在32位内核下)所不能做的。x86-64不提供32位进程利用在64位内核下运行的方式。(除了将远jmp转换为64位代码段,但大多数操作系统不支持这一点,编译器肯定不会发出代码来实现这一点。当然,使用全部4GB的地址空间,但就实际的机器代码指令而言,没有任何东西。)因此,您不希望编译器使用任何只能在64位内核下的32位模式下工作的功能。


TL:DR:
-m32-march=x86-64
可以解释为“通用x86-64 CPU的目标兼容/保护模式”。


实际上,它实际上只是意味着“启用这组ISA扩展”,这个名称对GCC来说并不比
-march=foobarbaz
-mtune=intel
更有意义,它只是一个用于调整表和ISA扩展设置的文本字符串。
不,64位指令不能在32位操作系统下使用(甚至在64位内核下的32位用户空间中),这不是
-march=x86-64
的意思


-march=x86-64
表示目标CPU支持x86-64保证的ISA扩展基线集:SSE2、P6功能,如CMOV、CPUID、RDTSC等。但如果没有
-m64
,代码仍将在32位模式下工作

(对于x86-64的目标ISA,它们本身并不是“扩展”。但我们仍然通常说x86-64意味着SSE和SSE2,因为这是一种对在XMM寄存器上运行的指令进行分类的简便方法。如果我们将x86-64本身视为x86的扩展,这是有意义的。)

所以
-march=x86-64
-march=k8
-march=nocona
(特定早期x86-64 CPU)非常相似。就像这些选项一样,它对
-m32
完全有效,并不意味着生成64位代码。 GCC仍然知道(从
-m32
)它的目标是32位模式(受保护或兼容模式),而不是64位长模式

由于这些模式使用不兼容的机器代码格式,因此与16位到32位的转换完全不同,在转换16位代码时,您可能希望编译器使用32位寄存器。在x86-64中,64位寄存器只能在长模式下使用,而不能在兼容模式或传统模式的任何子模式下使用(例如保护模式)。请参阅

这里的关键点是,32位进程在兼容模式下(在64位内核下)所能做的事情,在保护模式下(在32位内核下)所不能做的事情。x86-64并没有为32位进程提供一种方法来利用在64位内核下运行的优势。(除了将远jmp转换为64位代码段,但大多数操作系统不支持这一点,编译器肯定不会发出代码来实现这一点。当然,使用全部4GB的地址空间,但就实际的机器代码指令而言,没有任何东西。)因此,您不希望编译器使用任何只能在64位内核下的32位模式下工作的功能。


TL:DR:
-m32-march=x86-64
可以解释