英文:
How to use assembly to tell which kind of cpu is present
问题
所以由于我正在学习汇编,不同的CPU类型使用不同的特性或寄存器,有没有办法编写代码并区分ARM、Intel或AMD处理器?
我一直在进行研究,但没有找到任何信息。
编辑:
这个问题的目的是确定我们将为所有平台创建汇编代码,它们是否会根据CPU和架构来运行,而不是必须为每个平台创建单独的构建以便更容易。尽管从评论中看来,似乎你需要为每个平台单独开发。
英文:
So since I am learning assembly and difference CPU types use different features or registers differently. Is there a way to be able to code and tell the difference between ARM,Intel, or AMD processors?
I have been researching and haven't found anything.
EDIT:
The Purpose of this question was to determine that we would be creating assembly code for all platforms and if they would run based on the CPU and architecture alone rather than having to create seperate builds for each to make it easier. Although from the comments it seems you develop for each platform seperately
答案1
得分: 3
关键词要查找的是"CPU检测"或"CPU识别"。
在区分不同体系结构,如ARM与英特尔(x86)之间,这个问题是无意义的。在汇编级别,你必须选择一个体系结构来决定首先要编写什么指令。例如,如果你想要将两个数字相加,你会写add eax, ebx
(汇编为字节01 d8
),还是写add x0, x1, x2
(汇编为20 00 02 8b
)?在前一种情况下,你正在为x86编写。为了到达你所谓的体系结构检测代码,你必须执行许多先前的指令,这些指令只能在x86上运行,所以当你到达那里时,你已经知道答案。在后一种情况下,你正在为ARM(ARM64)编写。
(从技术上讲,相同的字节序列在两种体系结构上都会执行某种操作;但在另一种体系结构上,它肯定不会是你想要的。通常汇编程序/链接程序会使用正确的体系结构标记你的可执行文件,如果与正在运行它的机器不匹配,操作系统将拒绝执行它。)
要区分相同体系结构的CPU,首先必须决定是哪种体系结构,因为方法可能会非常不同。一般来说,通常有一些特殊的指令可以返回有关CPU的信息。在x86上,主要使用cpuid
,在ARM64上有各种使用mrs
访问的系统寄存器,等等。关于它们的工作原理以及如何解释结果,你必须查阅该体系结构的指令集参考文档。
特别是对于x86,多年来已经发布了许多不同的x86 CPU(英特尔、AMD和其他现在已经不存在的竞争对手之间),因此检测可能非常复杂,取决于你希望追溯到多远。 (例如,cpuid
指令并不总是存在,因此在区分较旧的CPU,比如2000年之前的CPU时,可能需要编写一篇很长的文章。)如今,还存在另一个问题,你的程序可能甚至不在x86硬件上运行,而可能是在模拟x86的其他CPU的虚拟机中运行。
对于大多数情况来说,一般问题"我如何知道CPU是哪种类型"并不是正确的问题。相反,首先要确定你感兴趣的特定CPU功能(例如AVX指令、增强的rep movsb
等),然后询问"我如何知道这个CPU是否支持它"?然后通常会有一个简单的答案,例如"将0x1234加载到eax
中,执行CPUID指令,并检查ecx
的第7位"(虚构的例子)。除此之外,写大量代码来区分Brandy Lake i8-1234U(2035 MHz)和Vodka Lake i9-9876Z(3107 MHz)之间的差异是没有意义的;原则上你可以找出你正在运行的是哪一个,但作为程序员,你实际上没有理由在意。
英文:
The key words to look for would be "CPU detection" or "CPU identification".
For distinguishing between architectures, like ARM vs Intel (x86), the question is moot. At the level of assembly, you had to pick an architecture to decide what instructions to code in the first place. For instance, if you wanted to add two numbers, did you write add eax, ebx
(assembling to the bytes 01 d8
), or did you write add x0, x1, x2
(assembling to 20 00 02 8b
)? In the former case, you're writing for x86. In order to get to your supposed architecture detection code in the first place, you had to execute a lot of previous instructions that would only run on x86, so by the time you get there, you already know the answer. In the latter case you're writing for ARM (ARM64).
(Technically the same sequence of bytes will do something on both architectures; but on the other one, it surely won't be what you want. Usually the assembler/linker would tag your executable with the correct architecture, and if it doesn't match the machine where it's being run, the operating system will refuse to execute it.)
For distinguishing between CPUs of the same architecture, you first have to decide which architecture that is, as the methods will likely be very different. Very generally, there is usually some special instruction which returns information about the CPU. On x86 you mainly use cpuid
, on ARM64 there are various system registers accessed with mrs
, and so on. For how they work, and how to interpret the results, you have to consult the instruction set reference for that architecture.
For x86 in particular, there have been so many different x86 CPUs released over the years (between Intel, AMD, and other now-defunct competitors) that detection can be very complicated, depending how far back you want to go. (For instance, the cpuid
instruction hasn't always existed, so the issue distinguishing between older CPUs, say pre-2000, could fill a long article.) Nowadays, there's the extra issue that your program may not even be running on x86 hardware, but may instead be in a VM with some other CPU that emulates x86.
For most purposes, the general question of "how do I tell which kind of CPU" is not really the right question to ask. Rather, identify the particular CPU feature you are interested in using (e.g. AVX instructions, enhanced rep movsb
, etc), and then ask "how do I tell whether this CPU supports it"? Then usually there is a simple answer, e.g. "load 0x1234 into eax
, execute CPUID, and check bit 7 of ecx
" (made up example). Beyond that, there's no point in writing a lot of code to tell the difference between a Brandy Lake i8-1234U at 2035 MHz or a Vodka Lake i9-9876Z at 3107 MHz; in principle you could find out which one you are running on, but as a programmer you have no actual reason to care.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论