CPUID
CPUID
指令是一条x86架构中的的扩展指令(此处的扩展指相对i80386),其操作码助记符缩写于“CPU识别”(CPU Identification),其作用是返回特定的CPU信息,使得软件可以在运行时检测CPU的硬件特性,以便于识别并决定运行哪些代码。首批支持CPUID指令的处理器是1993年发布的奔腾(i586)和486SL。[1]
通过使用CPUID
,软件可以确定处理器的类型和特性支持(例如MMX/SSE)。CPUID
操作码为0Fh、A2h。在调用CPUID前EAX寄存器内的值作为其输入参数,Intel64指令集手册中称其为“叶”(Leaf),AMD64指令集手册中称“功能码”(Function Number),执行CPUID后,返回值将被写入EAX,EBX,ECX和EDX寄存器内。此外,在使用一些特殊的输入参数时,必须同时于ECX内写入第二个输入参数,否则无法得到有意义的返回值。第二个参数也被称为“子叶”(Sub Leaf)或“子功能码”(Sub Function)。
历史
CPUID前判断处理器型号的方法
在CPUID
指令被引入前,若要在运行时确定CPU的型号,需要编写晦涩的汇编语言代码以判断某些指令被执行后处理器的行为。
1990年以前,对于如何判断CPU的型号没有官方说明与实现方法,但软硬件工程师们总结了一套利用PUSHF/POPF指令检测CPU行为以判断其架构的方法。此方法在广泛应用的同时引起了巨大争议,反对者认为其并非万无一失,在某些需要高可靠性的软件平台上若处理器型号判断错误,则有可能造成巨大损失,但英特尔在1990年发布了《i486微处理器程序员参考手册》(i486 Microprocessor Programmer's Reference Manual Intel Corp. 1990),其中在手册的第22.10节中使用了上述方法判断CPU代数,并且英特尔声称“代码序列已经过 Intel 验证,可以检测 CPUID、数学协处理器功能,并进行相应的初始化。任何其他方法都可能在未来的处理器中产生不可预测的结果”。此后该方法被应用于大多数操作系统内核中。
以下所介绍之方法为英特尔手册中的官方算法。
该算法的核心是利用PUSHF/POPF指令将标志寄存器中的特定位设为1或0,并观察处理器随后的行为,每一代处理器的具体行为均有所不同。
8086/8088系列处理器在清除标志寄存器的12-15位后,无论向其中写入何值,处理器将始终把它们设为1,其检测方式如下
pushf ; 将标志寄存器内容压栈
pop ax ; 将标志寄存器内容送入AX
mov cx, ax ; 将标志寄存器内容送入CX备份
and ax, 0fffh ; 将AX的12-15位置零
push ax ; 将标志寄存器的新值压栈
popf ; 送入FLAG
pushf ; 获取弹栈后标志寄存器的内容
pop ax ; 存入AX
and ax, 0f000h ; 如果12-15位被处理器置1则为8086/8088
cmp ax, 0f000h
je end_cpu_type_8688 ; 跳转至对应代码
对于80286系列处理器,在实模式下这些位始终被清零,在保护模式下,其用于I/O特权级别和嵌套任务(NT),其检测方法如下,代码接上述代码执行
or cx, 0f000h ; 将12-15位置1
push cx ; 压栈
popf ; 将栈内容弹入标志寄存器
pushf ; 获取标志寄存器并存入AX
pop ax
and ax, 0f000h ; 若12-15位位0则为286
jz end_cpu_type_286
检测386/486处理器的原理与上述代码相同,但检测的位有所区别,486处理器中引入了一个AC标志位,并将把它置1,其对于386而言是无效的,故386处理器将其置零,其实现如下
pushfd;EFLAGS压栈
pop eax ;获取原始 EFLAGS
mov ecx, eax ;保存原来的 EFLAGS
xor eax, 40000h ; 翻转 EFLAGS 中的 AC 位
push eax ;将新的 EFLAGS 压栈
popfd 中;替换当前的 EFLAGS 值
pushfd;获取新的 EFLAGS
pop eax ;将新的 EFLAGS 存储在 EAX
xor eax, ecx 中;无法反转AC则为386
jz end_cpu_type_386 ;如果 80386 处理器
此外,80386处理器的EDX寄存器在处理器被硬件复位后将被初始化为处理器的修订版本号。
奔腾处理器支持使用CPUID指令,因此其标志位中设置了一个被称为ID的特殊标志,若该标志存在,则对应的处理器支持CPUID,检测实现如下
mov eax, ecx ; 获取原始 EFLAGS
xor eax, 200000h ;翻转 EFLAGS 中的 ID 位
push eax ;将新的 EFLAGS 值保存在堆栈
popfd 中;替换当前的 EFLAGS 值
pushfd ;获取新的 EFLAGS
pop eax ;将新的 EFLAGS 存储在 EAX
xor eax, ecx 中;可切换则为奔腾或486SL
jne end_cpu_type_586
关于上述方法的注意事项
该算法无法检测80186处理器(虽然其并未被广泛使用),80186/88处理器包80286中包含的大部分新指令和异常,包括PUSHA/POPA、PUSH、SHL和无效操作码异常。80186/88中唯一没有实现的是专门用于保护模式的指令和异常。未能检测到此处理器可能会禁止使用某些可以利用这些新指令和异常的软件。
同时,由于PUSHF/POPF是Ring0指令,故该算法只能在实模式中执行,保护模式操作系统中运行的应用程序无法使用这个方法,除非处理器以及操作系统支持虚拟模式扩展(VME)。
以上算法仅供参考与学习,在使用非英特尔处理器,完全软件虚拟化(Full emulation)的虚拟机或其他平台上,该算法很有可能无法正确判断处理器支持的指令集。考虑到奔腾已经是近30年前的处理器,除非有必要在古老的计算机上检测CPU,否则不应该再使用这种算法,而是直接调用CPUID指令。
对于非x86架构的CPU,仍然需要精心设计的代码判断其差别(例如使用MOVE的特权要求判断摩托罗拉68000和68010),但大多数架构都要求具体实现者提供相应的寄存器以提供区分和判断处理器(例如ARM64的ID_AA64寄存器)。
调用CPUID
CPUID
指令的操作码是 0F A2
。CPUID
没有显式的操作数,其隐式使用EAX或EAX与ECX中的值作为参数,以确定要获取的信息。在英特尔指令集手册中,CPUID
的输入参数(EAX),被称为“叶”(Leaf),AMD称其为“功能码”(Function Number),执行CPUID后,返回值将被写入EAX,EBX,ECX和EDX寄存器内。此外,在使用一些特殊的输入参数时,必须同时于ECX内写入第二个输入参数,否则无法得到有意义的返回值。第二个参数也被称为“子叶”(Sub Leaf)或“子功能码”(Sub Function)。
注意,当且仅当MSR寄存器IA32_MISC_ENABLE.BOOT_NT4 的第22位为0时,EAX大于3的输入才是有意义的。当且仅当该位被设为1时,Windows NT 4.0 SP6以前的操作系统才能正常启动。
截止到2022年,对于一些常见的处理器架构,最大的有效的基础输入是0x20(GoldenCove),0x10(Zen4);最大有效的扩展输入是0x80000008(GoldenCove),0x80000028(Zen4)。
EAX=0: 最高基础输入参数与制造商ID
输入参数位0时,CPUID返回对当前处理器有意义的(即被当前架构所实现的)最大输入参数以及ASCII编码的制造商ID(Manufacturer ID)。
最大输入参数被写入EAX寄存器中,对于英特尔和AMD处理器,已知的返回值如下表所示:
架构 | 基础输入 | 扩展输入 |
---|---|---|
80486及以前 | 不支持CPUID指令 | |
486和P5 | 0x01 | 不支持 |
P6 | 0x02 | 不支持 |
P6(奔腾III) | 0x03 | 不支持 |
Netbrust | 0x02 | 0x8000 0004 |
Netbrust(64位) | 0x05 | 0x8000 0008 |
Core | 0x0A | 0x8000 0008 |
Core(Penryn) | 0x0D | 0x8000 0008 |
Bonnell | 0x0A | 0x8000 0008 |
Nehalem | 0x0B | 0x8000 0008 |
Sandy Bridge | 0x0D | 0x8000 0008 |
Skylake | 0x16 | 0x8000 0008 |
SunnyCove | 0x1B | 0x8000 0008 |
SunnyCove(Alder Lake) | 0x20 | 0x8000 0008 |
SunnyCove(Sapphire Rapids) | 0x8000 0008 |
架构 | 基础输入 | 扩展输入 |
---|---|---|
K5以前 | 不支持CPUID指令 | |
K5 | 0x1 | 不支持 |
K5(Krypton) | 0x1 | 0x8000 0005 |
K6 | 0x1 | 0x8000 0006 |
K7 | 0x1 | 0x8000 0007 |
K8 | 0x1 | 0x8000 0018 |
K10 | 0x5 | 0x8000 001B |
K10(Llanro) | 0x6 | 0x8000 001B |
Bulldozer | 0xD | 0x8000 001E |
Zen | 0xD | 0x8000 001F |
Zen2 | 0x10 | 0x8000 0020 |
Zen3 | 0x10 | 0x8000 0023 |
Zen4 | 0x10 | 0x8000 0028 |
制造商ID含有12个字符,以EBX-EDX-ECX的顺序拼接,例如在英特尔处理器上将返回“GenuineIntel”,具体的返回值如下表所示:
寄存器 | 16进制值 | ASCII |
---|---|---|
EBX | 756E6547 | Genu |
ECX | 6C65746E | ntel |
EDX | 49656E69 | ineI |
已知的制造商以及其ID如下:
"AMDisbetter!"
– AMD K5的早期工程样品"AuthenticAMD"
– AMD"CentaurHauls"
– IDT/半人马座(Centaur)/兆芯"CyrixInstead"
– Cyrix/意法半导体/IBM"GenuineIntel"
– 英特尔"TransmetaCPU"
– 全美达"GenuineTMx86"
– 全美达"Geode by NSC"
– 国家半导体"NexGenDriven"
– NexGen"RiseRiseRise"
– Rise"SiS SiS SiS "
– 矽统"UMC UMC UMC "
– 联华电子(台联电)"VIA VIA VIA "
– 威盛"Vortex86 SoC"
– DM&P Vortex86" Shanghai "
– 兆芯"HygonGenuine"
– 海光"Genuine RDC"
– RDC"E2K MACHINE"
– MCST Elbrus
已知的软核x86处理器ID:
"MiSTer AO486"
– ao486"GenuineIntel"
– v586
已知的x86虚拟机ID:
"bhyve bhyve "
– bhyve" KVMKVMKVM "
– KVM"TCGTCGTCGTCG"
– QEMU"Microsoft Hv"
– Hyper-V"MicrosoftXTA"
– 微软x86到ARM转译器" lrpepyh vr"
– Parallels"VMwareVMware"
– VMware"XenVMMXenVMM"
– Xen HVM"ACRNACRNACRN"
– Project ACRN" QNXQVMBSQG "
– QNX"GenuineIntel"
– 苹果 罗塞塔2 x86到ARM转译器"VirtualApple"
– 苹果 罗塞塔2 x86到ARM转译器
使用GNU格式汇编语言获取制造商ID和最高输入的例子:
.data
s0: .asciz "CPUID: %x\n"
s1: .asciz "Largest basic function number implemented: %i\n"
s2: .asciz "Vendor ID: %.12s\n"
.text
.align 32
.globl main
main:
pushq %rbp
movq %rsp,%rbp
subq $16,%rsp
movl $1,%eax
cpuid
leaq s0(%rip),%rdi
movl %eax,%esi
xorl %eax,%eax
call printf
pushq %rbx
xorl %eax,%eax
cpuid
movl %ebx,8(%rsp)
movl %edx,12(%rsp)
movl %ecx,16(%rsp)
popq %rbx
leaq s1(%rip),%rdi
movl %eax,%esi
xorl %eax,%eax
call printf
leaq s2(%rip),%rdi
movq %rsp,%rsi
xorl %eax,%eax
call printf
movq %rbp,%rsp
popq %rbp
// ret
movl $1,%eax
int $0x80
EAX=1: 处理器信息和特性
该参数在EAX中返回处理器的版本信息,这些信息也被称为“签名”(signature),一般而言,对于使用同一工艺制造的同一架构的处理器,其签名是相同的,故该信息可被用于判断架构和工艺。其包含的内容以及意义如下:
EAX | |||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
保留=0 | 扩展系列号(Extended Family ID) | 扩展型号(Extended Model) | 保留=0 | 处理器类型(Type) | 系列号(Family) | 型号(Model) | 步进(Stepping) |
关于版本信息的注意事项:
- 若系列号部分为0xF,则实际的系列号为EAX中系列号字段和扩展系列号字段的和,反之实际系列号与EAX中字段相同。
- 若系列号部分为0xF或6,则实际的型号为EAX中扩展型号字段左移四位后与型号字段的和,反之实际型号与EAX中字段相同。
上述内容用伪代码表示:
IF Family_ID ≠ 0FH
THEN DisplayFamily = Family_ID;
ELSE DisplayFamily = Extended_Family_ID + Family_ID;
END;
IF (Family_ID = 06H or Family_ID = 0FH)
THEN DisplayModel = (Extended_Model_ID « 4) + Model_ID;
ELSE DisplayModel = Model_ID;
END;
步进表示对处理器的修正或使用不同工艺制造,其具体意义应当参考处理器厂商所发布的手册。
其中,处理器类型(Type)的编码如下:
类型 | 二进制编码 |
---|---|
默认,一般OEM处理器 | 00 |
Overdrive处理器 | 01 |
双处理器 | 10 |
保留 | 11 |
EBX中返回处理器的附加信息,其内容被分为以下几个字段:
字段 | EBX | 说明 |
---|---|---|
7:0 | 处理器名称索引号(Brand Index) | |
15:8 | CLFLUSH指令清除缓存的大小 | 仅当CPU支持CLFLUSH指令时
(CPUID.01.EDX.CLFSH [bit 19]= 1)有效 |
23:16 | 对于AMD处理器,若HTT标志(位于CPUID Fn0000_0001_EDX)为1,则该字段为该处理器的逻辑核心(即线程)数,反之,该字段无意义且为0。
对于Intel处理器,若与上述相同位置的HT标志有效,则该字段代表该架构处理器中可寻址的最大APIC ID数量,(注意:这个值不是逻辑处理器数),在奔腾4HT及以前的处理器中,该字段代表每个物理核心对应的逻辑处理器数量。 |
无论是何种处理器,该字段只在HT标志有效时有意义。 |
31:24 | 初始Local APIC ID | 该值已被x2APIC ID取代 |
ECX和EDX返回处理器实现的功能,一个二进制位代表一个功能,该位为1是表示处理器支持该功能,反之则不支持,各位对应功能或指令如下:
位 | EDX | ECX | ||
---|---|---|---|---|
简称 | 描述 | 简称 | 描述 | |
0 | fpu | 集成FPU(Onboard x87 FPU) | sse3 | 流式SIMD扩展3(SSE3或Prescott新指令(PNI)) |
1 | vme | 虚拟8086模式扩展(Virtual 8086 mode extensions) | pclmulqdq | PCLMULQDQ指令 |
2 | de | 调试扩展(Debugging extensions CR4 bit 3) | dtes64 | 64位Debug store (edx bit 21) |
3 | pse | 页尺寸扩展(Page Size Extension) | monitor | MONITOR和MWAIT指令 |
4 | tsc | 时钟周期计数器(Time Stamp Counter) | ds-cpl | CPL qualified debug store |
5 | msr | 特殊模块寄存器(Model-Specific Registers) | vmx | 虚拟机扩展(Virtual Machine eXtensions,VMX) |
6 | pae | 物理地址扩展(Physical Address Extension) | smx | 安全模式扩展(Safer Mode Extensions) |
7 | mce | 机器检查异常(Machine Check Exception) | est | 增强SpeedStep(Enhanced Intel SpeedStep,EIST) |
8 | cx8 | CMPXCHG8指令 | tm2 | 温度传感器2(Thermal Monitor 2) |
9 | apic | 集成高级可编程中断控制器(Advanced Programmable Interrupt Controller) | ssse3 | 流式SIMD扩展3补充指令集(Supplemental SSE3,SSSE3) |
10 | 保留 | cnxt-id | 一级缓存上下文ID(L1 Context ID) | |
11 | sep | SYSENTER和SYSEXIT指令 | sdbg | Silicon Debug interface |
12 | mtrr | 内存类型范围寄存器(Memory Type Range Registers) | fma | 3操作数融合乘加(Fused multiply-add 3,FMA3) |
13 | pge | 全局分页控制位(Page Global Enable bit in CR4) | cx16 | CMPXCHG16B指令 |
14 | mca | 机器检查架构(Machine check architecture) | xtpr | Can disable sending task priority messages |
15 | cmov | 条件传送指令(CMOV) | pdcm | Perfmon & debug capability |
16 | pat | 页属性表(Page Attribute Table) | 保留 | |
17 | pse-36 | 36位页尺寸扩展(36-bit page size extension) | pcid | Process context identifiers (CR4 bit 17) |
18 | psn | 处理器序列号(Processor Serial Number) | dca | Direct cache access for DMA writes[2][3] |
19 | clfsh | CLFLUSH指令 | sse4.1 | 流式SIMD扩展4.1(SSE4.1) |
20 | 保留 | sse4.2 | 流式SIMD扩展4.2(SSE4.2) | |
21 | ds | 调试保存(Debug store) | x2apic | x2APIC |
22 | acpi | 集成ACPI温控寄存器(Onboard thermal control MSRs for ACPI) | movbe | MOVBE指令 |
23 | mmx | 多媒体扩展(MMX) | popcnt | POPCNT指令 |
24 | fxsr | FXSAVE,FXRESTOR 指令 | tsc-deadline | APIC implements one-shot operation using a TSC deadline value |
25 | sse | 流式SIMD扩展(SSE或Katmai新指令) | aes | AES指令集 |
26 | sse2 | 流式SIMD扩展2(SSE2) | xsave | XSAVE, XRESTOR, XSETBV, XGETBV指令 |
27 | ss | 自窥探缓存(self-snoop cache) | osxsave | 操作系统启用XSAVE |
28 | htt | 超线程(Hyper-threading) | avx | 高级矢量扩展(Advanced Vector Extensions,AVX) |
29 | tm | 自控温温度传感器(Thermal monitor automatically limits temperature) | f16c | F16C指令集 |
30 | ia64 | 基于IA64架构的处理器 | rdrnd | 集成随机数发生器on-chip random number generator) |
31 | pbe | 挂起中断(Pending Break Enable) | hypervisor | 当前为虚拟机环境 |
EAX=2: 缓存和TLB信息(英特尔)
对于英特尔处理器,EAX=2将返回处理器缓存,TLB和预取器信息,这些信息被编码为数个1字节信息返回于EAX,EBX,ECX和EDX四个寄存器中,编码规则如下:
EAX寄存器返回值的最低位(LSB)一定是1,它不代表任何信息,软件读取时应当将其忽略。
每个寄存器返回值的最高位(MSB)代表该寄存器中的值是否有效,若MSB为0,则该寄存器包含有意义的信息,反之则代表该寄存器为保留值且无意义。
若某一寄存器内的返回值有意义,则其应当被分割为4个等长部分,每部分长度为8为,即一字节,每部分代表了一个缓存/TLB或预取器的信息,具体编码见英特尔所发行的官方手册Intel 64 and IA-32 Architectures Software Developer Manuals (页面存档备份,存于互联网档案馆) 卷2A中关于CPUID指令的表3-12。(截至2023.2,该表位于Vol2A,3-245到3-248页)。
关于EAX=2的注意事项
代表缓存/TLB/预取的编码字节没有特定的顺序,不存在“某个寄存器的某个字节对应于哪一级别的缓存”。
使用EAX=2是获取英特尔处理器缓存信息的传统方法,但由于缓存类型迅速增多,使用该方法已经无法高效的获取信息,故对于较新的(一般认为是Core及以后)的英特尔处理器,返回值的编码中可能包含类似0xFF或0的空描述符,对于此种情况,应当使用更新的方法(EAX=4)获取缓存信息。
对于AMD处理器,EAX=2是保留项。四个寄存器都将返回0。
EAX=3处理器序列号(英特尔)
以3作为输入参数时,CPUID将在ECX和EDX寄存器中返回处理器序列号。
关于EAX=3的注意事项
该参数仅在使用核心代号为Katmai和Coppermine的奔腾III处理器上可用,处理器序列号是一个独一无二的96位长的二进制数(实际只使用了64位),每个处理器仅对应一个序列号,通过序列号可用追踪该处理器从生产到销售使用的全部流程,英特尔自称引入该功能的原因是“为了提高电子商务安全性,例如只能在某台电脑上使用某张银行卡”,但其在中美欧等多个国家和地区引起了强烈的隐私和国家安全问题争议,民间认为该功能侵犯了用户隐私权,居心不良者可用该功能追踪他人的计算机,且一旦英特尔的序列号数据库泄露,将带来难以估量的损失,而多国的国家安全机关认为,敌对国家的情报部门可以使用该功能轻而易举的记录并分析计算机活动,迫于市场压力,英特尔从核心代号Tulatin的奔腾III处理器开始禁用了这一功能,且在奔腾4以及Core处理器等后续产品上再未使用过该功能。
对于AMD处理器,EAX=3是保留项。四个寄存器都将返回0。
EAX=4缓存参数(英特尔)
以4作为EAX输入参数时,CPUID依据ECX寄存器中输入的第二个参数(也称为子叶)返回处理器缓存信息。
EAX返回缓存类型信息,值分为以下几个字段
EAX | ||
---|---|---|
位 | 内容 | 备注 |
4:0 | 缓存类型 | 00:空
01:数据缓存 10:指令缓存 11:数据和指令缓存 |
7:5 | 缓存级别 | 从1开始 |
8 | 自初始化缓存标志 | 为1则支持自初始化,反之需要软件初始化 |
9 | 全相联缓存标志 | 同上 |
13:10 | 保留=0 | |
25:14 | 最大共享此缓存的线程数 | 1.指逻辑处理器,需考虑超线程
2.为最大值,不一定代表真实值 3.用于计算时将该字段值+1 |
31:26 | 最大可寻址的核心ID | 同上 |
EBX,ECX返回缓存尺寸信息,返回值各个字段如下:
EBX | ||
---|---|---|
位 | 内容 | 备注 |
11:0 | 缓存线尺寸(Line Size,L) | 1.以字节为单位
2.真实值为该字段+1 |
21:12 | 物理缓存分区数(Physical Line partitions,P) | 真实值为该字段+1 |
31:22 | 缓存组行数(Ways of associativity,W) | 同上 |
ECX返回组相联缓存的的组数(Sets,S)。
关于EAX=4的注意事项
关于子叶的意义以及最大支持的子叶
英特尔并未在其发布的官方手册中定义子叶与缓存的绝对对应关系,也未说明最大支持的子叶,上述关系表格只是软硬件工程师的总结,但截止到2023年的SunnyCove架构,所有的英特尔处理器都遵守这一对应关系。
在面对一个全新的英特尔架构时,应当假定上述对应关系与最大子叶数不存在,并通过该指令判断,其中对应关系由上述EAX中的返回值相应字段确定,最大子叶值由以下方法判断:在EAX输入4,ECX中的初始值为0并执行CPUID指令,每次执行后将ECX内值加1,EAX仍为4,直到四个寄存器的返回值全部为0,则使返回值不为0的最大ECX输入就是最大支持的子叶。
对于AMD处理器,EAX=3是保留项。四个寄存器都将返回0。
关于缓存尺寸的计算
英特尔SDM手册中未直接给出读取缓存尺寸的方法,但可以通过如下公式计算:
其中C为以字节为单位的缓存大小,W,P,L,S为读取该缓存时返回值的相应字段。
x86外的特定CPU识别信息
一些非x86的CPU架构也提供了有关处理器能力的某种形式的结构化信息,通常作为一组特殊寄存器:
参见
参考资料
- ^ Intel 64 and IA-32 Architectures Software Developer’s Manual (PDF). Intel.com. [2013-04-11]. (原始内容存档 (PDF)于2009-04-19).
- ^ Huggahalli, Ram; Iyer, Ravi; Tetrick, Scott. Direct Cache Access for High Bandwidth Network I/O. ACM SIGARCH Computer Architecture News. 2005, 33 (2): 50–59. doi:10.1145/1080695.1069976. CiteSeerX:10.1.1.91.957.
- ^ Drepper, Ulrich, What Every Programmer Should Know About Memory, 2007, CiteSeerX:10.1.1.91.957
- ^ ARM Information Center. Infocenter.arm.com. [2013-04-11]. (原始内容存档于2013-05-27).
- ^ Processor version codes and SRM constants. [2014-09-08]. (原始内容存档于2014-09-08).
- ^ IBM System z10 Enterprise Class Technical Guide (PDF). [2017-04-10]. (原始内容存档 (PDF)于2017-08-29).
- ^ MIPS32 Architecture For Programmers, Volume III: The MIPS32 Privileged Resource Architecture (PDF). MIPS Technologies, Inc. 2001-03-12 [2017-04-10]. (原始内容存档 (PDF)于2016-03-04).
- ^ PowerPC Operating Environment Architecture, book III (PDF). [2017-04-10]. (原始内容存档 (PDF)于2016-03-04).