However, I really want to learn about assembly, and how it's used in modern day applications.
在“普通”PC 上,它仅用于时间关键的处理,我想说,实时多媒体处理仍然可以从手工锻造装配中受益匪浅。在嵌入式系统上,马力要少得多,它可能有更多的使用领域。
但是,请记住,这不仅仅是“嘿,这段代码很慢,我将用汇编重写它,它会神奇地变快”:它必须仔细编写汇编,编写knowing在您的特定架构上,什么是快的,什么是慢的,并牢记现代处理器的所有复杂性(分支错误预测、无序执行……)。通常,初级到中级汇编程序员编写的汇编程序将是slower比由优秀的现代优化编译器生成的最终机器代码更好。 x86 上的性能问题通常非常复杂,应该留给那些知道自己在做什么的人 => 他们中的大多数都是编译器编写者。 :) 看一下this http://web.archive.org/web/20160801143844/https://blogs.msdn.microsoft.com/oldnewthing/20041216-00/?p=36973/, 例如。用于测试 Collatz 猜想的 C++ 代码比手写汇编更快 - 为什么? https://stackoverflow.com/questions/40354978/c-code-for-testing-the-collatz-conjecture-faster-than-hand-written-assembly深入了解该情况下的一些特定 x86 细节,您必须了解这些细节才能在单个小循环中匹配或击败启用优化的编译器。
I know processors have different instruction sets above the basic x86 instruction set. Do all assembly languages support all instruction sets?
我认为你在这里混淆了一些事情。许多(=全部现代)x86
处理器支持在原始指令和指令集之后引入的附加指令和指令集x86
指令集被定义。实际上,现在几乎所有 x86 软件都是为了利用后 Pentium 功能而编译的,例如cmovcc https://www.felixcloutier.com/x86/cmovcc;您可以使用以下命令查询处理器以查看它是否支持某些功能CPUID http://en.wikipedia.org/wiki/CPUID操作说明。显然,如果您想对某些较新的指令集指令使用助记符,您的汇编器(即在实际机器代码中翻译助记符的软件)必须了解它们。
大多数 C 编译器都有内在函数 like _mm_popcnt_u32
和/或命令行选项,例如-mpopcnt
使它们能够让您利用新指令而无需手写汇编。 x86-mbmi
/ -mbmi2
扩展有几个编译器知道如何在优化普通 C 时使用的指令,例如x << y
(shlx https://www.felixcloutier.com/x86/sarx:shlx:shrx而不是更笨重的shl https://www.felixcloutier.com/x86/sal:sar:shl:shr) or x &= x-1;
(blsr / _blsr_u32() https://www.felixcloutier.com/x86/blsr)。海湾合作委员会有一个-march=native
选项启用您的 CPU 支持的所有指令集,并设置-mtune=
根据循环展开量或哪些指令或序列在一个 CPU 上更快、在另一个 CPU 上更慢来优化 CPU 是一个好主意。
相反,如果您正在谈论其他系列处理器的其他(非 x86)指令集,那么每个汇编器都应该支持目标处理器可以运行的指令。并非汇编语言的所有指令都可以直接替换其他语言,并且通常将汇编代码从一种体系结构移植到另一种体系结构通常是一项艰巨的工作。
How many assembly languages are there?
理论上,每个处理器系列至少有一种方言。请记住,同一汇编语言也有不同的表示法;例如,以下两条指令是用 AT&T 和 Intel 表示法编写的相同 x86 内容:
mov $4, %eax // AT&T notation
mov eax, 4 // Intel notation
How would someone go about writing a routine in assembly, and then compiling it in to object/binary code?
如果您想将例程嵌入到用另一种语言编写的应用程序中,您应该使用该语言提供的工具,在 C/C++ 中您可以使用asm
blocks.
您可以改为独立制作.s
or .asm
例如,使用与 C 编译器输出相同语法的文件gcc -O3 -S
将编译为.s
您可以使用它进行汇编的文件gcc -c
。如果您想在 asm 中编写整个函数而不是包装一条或几条指令,那么单独的文件是一个好主意。 x264 和 x265(视频编码器)等一些开源项目拥有大量 NASM 源代码,适用于不同版本的 SSE 或 AVX 的不同版本的功能。
相反,如果您想用汇编语言编写整个应用程序,则必须遵循您要使用的汇编器的语法规则,仅在汇编语言中编写。
How do we know the code we've written in assembly is the fastest it possibly can be?
理论上,因为它最接近裸机,所以您可以让机器完全按照您的意愿行事,而无需让编译器考虑在某些特定情况下无关紧要的语言功能。在实践中,由于机器通常比汇编语言公开的要复杂得多,正如我所说,汇编语言通常会比编译器生成的机器代码慢,因此考虑到了普通程序员不知道的许多微妙之处。
Addendum
我忘记了:知道阅读汇编,至少一点点,可以very对于调试优化器损坏时可能出现的奇怪问题很有用/仅在发布版本中/您必须处理 heisenbugs/当源代码级调试不可用或其他类似的东西时;看看评论here http://web.archive.org/web/20190118214328/https://blogs.msdn.microsoft.com/oldnewthing/20041111-00/?p=37333.