《Windows篇》
对于每天都要在windows平台上进行逆向工程任务的我们而言,稍微了解一些系统底层的机制与实现原理,用这些背景知识来武装自己总是好的。
调试器,反汇编器,加包,解包器,虚拟机,等等,无一不是运行在windows系统上,
甚至对内核调试器如SoftICE,WinDbg等工具的使用,也要求了解一些系统的内幕。
最近抽空在阅读《深入解析windows操作系统第6版上册》这本书,因此将其中与软件逆向有关的重点总结出来,部分内容加上了个人的理解进行润色,并非断章取义,而是去芜存菁。
笔记会不定期更新,对于某些作者的观点,尝试加入自己的实验过程来验证。
********************************
在windows系统架构中,运行在用户模式下的进程有4种基本类型,各自有其私有的进程地址空间:
1。固定的(或者硬性指定的)“系统支持进程“,比如登录(logon)进程,会话
管理器(session manager)进程,它们并不是windows服务,也就是说,它们不
是由“服务控制管理器”来启动的。登录进程名为winlogon.exe,即“windows登
录应用程序”,由此可见它是运行在用户模式下。会话管理器进程名为smss.exe,
所有用户模式进程在sysinternal的进程浏览器中,其“private bytes”列都会显示
出使用的字节数;相反,内核模式组件或服务,其private bytes列中没有数据;服
务控制管理器也是用户模式进程之一,其进程名为services.exe
2。服务进程,服务进程宿纳的是各种windows服务,这些服务可以通过运行services.msc来查看。windows服务往往要求独立于用户登录而运行(在用户登录前,以及用户不登录时,都必须运行)svchost.exe就是服务进程,运行在用户模式下。
3。用户应用程序
4。环境子系统服务进程
注意,服务进程与用户应用程序,并不直接调用原生的windows操作系统服务,而
是先调用一个或者多个子系统DLL(动态链接库)中的A函数,由A调用ntdll.dll中
的相应B函数,B再调用原生的windows操作系统服务,后者运行在内核模式。
由此可见,子系统DLL运行在用户模式,它扮演的角色即是,通过子系统DLL中一个已经文档化的windows API函数,最终调用原生的系统服务,这些服务通常是未文档化的。
(注意这里的系统服务与前面提到的windows服务是两个不同的事物)
补充说明,关于“子系统DLL的支持DLL”:ntdll.dll
ntdll.dll是一个特殊的系统支持库,主要被其它的子系统DLL使用。应用程序调用某
个子系统DLL中的windows API 函数,后者再调用ntdll.dll中的相应函数,例如
NtCreateFile,NtSetEvent等。(可以用depends walker 加载ntdll.dll,即可找到
这2个函数)
虽然这些以Nt开头的函数仍旧是运行在用户模式,但是这些函数内部的代码包含了
与处理器体系结构相关的“处理器特权模式”切换指令,通过该指令可以切换到内
核模式(或者说切换到Intel为处理器体系结构定义的4个安全级别中的“ring0
级”,在该级别下对处理器指令的使用将不受限制)
,从而调用内核模式下的“系统服务分发(调度)器”。系统服务分发器在检查某
些参数的合法性以后,再由它调用真正的内核模式系统服务,其中包括
Ntoskrnl.exe内部的实际代码。
也就是说,从用户模式到内核模式的转换点位于ntdll.dll中的函数内部。
在ntdll.dll中,编号从113开始到编号169的以Ldr开头的函数,实现了“映像加载器”的功能,PE文件加载器就实现在这些函数的内部。(例如LdrLoadDll,LdrShutdownProcess等)
另外,ntdll.dll中的一些函数还实现了“堆管理器”,windows子系统进程通信函数(以Csr前缀开头),提供用户模式调试支持的函数(以DbgUi前缀),以及windows事件跟踪支持的函数(以Etw前缀)
例如DbgBreakPoint,DbgUiConnectToDbg,DbgUiStopDebugging,用户模式调试器如OllyDbg,很可能直接或者间接地调用了这些调试函数。
再如,windows执行体(内核模式)中的“用户模式调试框架”例程,也负责向用户模式调试函数发送事件,支持断点与单步跟踪代码,以及改变运行线程的执行环境。可以这么认为,没有内核提供对用户模式调试函数的支持,OllyDbg等工具就无法通过调用调试函数实现调试功能。
在ntdll.dll的2000多个函数中,编号从1935到2033的函数是C运行时库(CRT)例程的子集,包括memcpy,strcpy,itoa等等。
********************************
********************************
在windows系统架构中,内核模式组件包括:
1。windows执行体:包含了基本的操作系统服务,比如内存管理,进程和线程管理,安全性,I/O,网络和跨进程通信。windows执行体是Ntoskrnl.exe中的上层(内核是其下层)。
执行体包含各种类型的函数:
@可在用户模式下调用的导出函数,这些函数称为“系统服务”(注意与“windows服务”的区别),并且通过ntdll.dll导出。这些服务绝大多数可以通过
windows API来访问,或者通过另一个环境子系统的API来访问。然而也有少数系统服务无法通过任何已经文档化的子系统DLL中的函数访问,例如NtQueryInformationProcess,NtCreatePagingFile等等。(这两个函数均通过
ntdll.dll导出)
@可通过DeviceIoControl函数来调用的设备驱动程序函数,这为从用户模式到内核模式提供了一个通用接口,因而在用户模式下可以调用设备驱动程序中并不与读或者写操作关联的函数。
@只能在内核模式下调用的导出函数,这些函数在WDK中已经文档化。
@只能在内核模式下调用,并且尚未在WDK中文档化的导出函数。
@定义为全局符号,但是未被导出的函数,这包括在Ntoskrnl内部调用的支持函数,例如以Iop前缀的函数(执行体组件的I/O管理器内部支持函数),
以Mi前缀的函数(执行体组件的内存管理器内部支持函数),明显在ntdll.dll中找不到这两种前缀的函数,因此未被“导出”。
@未定义成全局符号,而是在特定模块内部的函数(以static修饰?)
执行体包含的组件:
一。配置管理器:负责实现和管理系统的注册表。
二。进程管理器:创建和终止进程和线程,虽然针对进程与线程的支持是在windows内核(Ntoskrnl.exe的下层)中实现的,而执行体则在这些底层对象的基础上增加了额外的语义和功能。
三。I/O管理器:实现了与设备无关的I/O功能,负责将I/O请求分派到恰当的设备驱动程序进一步处理。
四。即插即用(PnP)监视器:在用户首次添加新硬件设备时,PnP监视器为了支持这些设备,必须负责寻找并加载最适合这些设备的驱动程序,同时,还需要为新设备分配硬件资源,例如这些设备与操作系统通信的I/O端口,IRQ(中断请求号),DMA(直接存储器访问)通道,以及在物理内存中的映射范围(如果该设备有“片上”存储器的话,例如显卡的显存)。
PnP监视器只负责新设备的驱动程序与硬件资源的指派,后续对该设备的I/O操作,就由I/O管理器来调度。当系统中的设备发生变化,例如增加或者移除设备时,它还负责发送恰当的事件通知。
services.msc列表中,对PnP服务的描述为:“使计算机在极少或没有用户输入的情况下能识别并适应硬件的更改。终止或禁用此服务会造成系统不稳定。”
很多其他服务,例如Windows Driver Foundation - User-mode Driver Framework(管理用户模式的驱动程序主机进程。)都依赖于内核模式的PnP监视器。
五。安全引用监视器:强制在本地计算机上实行安全策略,它守护着操作系统的资源,执行对“运行时对象”的保护和审计。
六。电源管理器:负责协调电源事件,并且产生电源管理I/O通知,发送给设备驱动程序,由后者控制对设备的电源管理。电源管理器可以配置成,当系统空闲时,通过将CPU置于睡眠状态而降低电源消耗。
七。缓存管理器:提高了基于文件的I/O操作的性能,其做法是,让最近引用过的磁盘数据驻留在内存中以便快速访问(并且延迟磁盘写操作,在将更新数据写入磁盘之前,在内存中停留一小段时间)缓存管理器依赖于内存管理器。
八。内存管理器:实现了虚拟内存,这是一种内存管理方案,为每个进程提供一个巨大的私有地址空间,其大小可以超过计算机系统当前实际可用的物理内存大小。
windows执行体还包含一些重要的“基础设施例程”如下:
一。内核调试器库:使得内核的调试与支持KD的调试器保持独立,内核调试器库提供对WinDbg与Kd.exe等内核调试工具的支持。
二。windows事件跟踪例程:为内核模式和用户模式组件提供了在整个系统范围内进行事件跟踪所需调用的例程。
三。文件系统运行库:为文件系统驱动提供了一组公共的支持例程。
2。windows内核:由一组低层次的操作系统功能构成,比如“线程调度”,中断, 异常分发(exception dispatching),以及多处理器同步。windows内核也提供了一组例程与基本对象,执行体的其余部分利用这些例程和对象实现更高层次的功能。
实际上,windows执行体与windows内核被集成在一个叫做 Ntoskrnl.exe 的内核
映像文件中,在32位windows系统上,这个文件叫做 Ntkrnlpa.exe 。
后者支持物理地址扩展,使得32位系统最多可以寻址64GB的物理内存。
注意,我们使用dependency walker加载32位windows 7 旗舰版的Ntkrnlpa.exe文
件,并查看这个文件的依赖关系后发现,该文件链接了hal.dll,kdcom.dll(为内核调
试器提供协议支持),以及pshed.dll(处理特定硬件体系结构的错误报告),这几
个重要的dll,而这3个dll都依赖于Ntoskrnl.exe,这就是为什么32位windows 7系
统上,同时存在Ntkrnlpa.exe 与Ntoskrnl.exe的原因。而在64位windows 7系统上
没有Ntkrnlpa.exe,因为Ntoskrnl.exe链接到的所有dll中,都没有Ntkrnlpa.exe
的依赖,因此后者在64位系统上被省略了。
如前所述,内核是由Ntoskrnl.exe下层中的一组函数以及对于硬件体系结构的底层
支持(例如中断和异常分发)构成的。Ntoskrnl.exe下层中的这组函数提供了一些
最为基本的机制,如“线程调度”和同步服务,供上层的执行体使用,而对于硬件
的底层支持则因处理器体系结构而异。内核主要用C语言编写,对于那些要用到特殊
的处理器指令和寄存器的任务(不容易通过编写C代码访问),则使用汇编语言编
写。
因为在实现,开发内核模式的驱动程序时,需要用到这一组函数,因此在WDK中有
相应的文档描述,以Ke为前缀的函数即是。
上层的执行体将线程和其它可共享的资源都表示为“对象”,执行体对象建立在内
核提供的“内核对象”基础之上,并且对后者进行封装。
执行体利用内核函数,创建和维护内核对象实例,并且构建更复杂的,提供给用户
模式的执行体对象。
3。设备驱动程序:既包括硬件设备驱动程序,也包括像文件系统和网络驱动程序(协议栈?)之类的非硬件设备驱动程序。其中硬件设备驱动程序将用户的I/O函数调用,转换成特定的硬件设备I/O请求。因此文件系统驱动与网络协议堆栈属于windows内核组件之一。设备驱动程序是可加载的内核模式模块,通常的扩展名为 .sys,前面有提到说设备驱动程序所处的位置在windows执行体的“I/O管理器”组件与硬件设备,两者的中间。
第三方硬件厂商开发的windows设备驱动程序并不直接与硬件打交道,而是通过调用hal.dll中的函数来切换到内核模式,从而间接操控硬件,因而许多hal.dll内
的支持例程与函数在WDK中已获得文档化,可供设备驱动程序开发人员参考。也就是说,实际上在硬件设备驱动程序的下面还有hal.dll,然后才是硬件。
必须强调的是,要在系统中添加“用户编写的内核模式代码”,安装驱动程序是唯一的方法,换个角度思考,即编写设备驱动程序是一种访问操作系统内部函数与数据结构的方式,在用户模式下它们通过windows API是不可访问的,除非使用WDK文档中提到的hal.dll接口函数。
例如,sysinternal的许多系统工具的内部架构是由前端的用户模式图形界面组成,前端使用windows API,而工具的“内核”则以设备驱动程序的身份调用windows内核模式下的函数,
如此才能搜集到许多系统内部的信息(这些信息包括windows内核维护的许多数据结构)。
从windows 2000中引入的驱动程序模型称为WDM,它将驱动程序分为3种:
一,总线驱动程序:为总线控制器,适配器,桥接器等总线相关的设备服务,windows通常内置了多数计算机系统上最常见的总线类型(如PCI,USB,PCMCIA)对应的总线驱动程序。
另外,由于总线实际位于主板上,因此主板制造商也会提供针对新的总线标准(如USB3.0总线控制器,XHCI)的驱动程序,可以通过光盘等存储介质作为windows内核模块的一部分安装并加载。
二, 功能驱动程序,即特定于硬件设备的驱动程序。
三,过滤驱动程序,用于为特定的硬件或对应的驱动程序增加新功能,或者修改来自其它驱动程序的I/O请求,应答等。
因此,在WDM中,windows执行体的PnP即插即用管理器通过“总线驱动程序”获得当前计算机系统各类总线上的设备信息概况;
windows执行体的I/O管理器则通过“功能驱动程序”对相应设备进行读写操作。
点击开始,运行,输入“msinfo32” 回车,选择系统摘要 -〉软件环境 -〉系统驱动程序,即可列出当前系统已安装的内核模式驱动程序,以及是否正在运行,其中包含了NTFS 文件系统驱动与TCP/IP协议驱动。
所有的内核模式驱动程序文件的扩展名为 .sys,且存放在c:\windows\system32\drivers\ 路径下。
值得注意的是,在物理机上判断vmware 是否启动了桥接模式网卡支持,可以查看系统驱动程序列表中,vmnetbridge VMware Bridge Protocol 这一项是否正在运行 。
该驱动的路径为 c:\windows\system32\drivers\vmnetbridge.sys
在安装或启动虚拟机时,如果vmware给出与vmx86相关的错误信息,也要在该列表中确认vmx86 VMware vmx86 这一项是否作为内核模块加载并且正在运行,该驱动的路径为 c:\windows\system32\drivers\vmx86.sys ,如果这两项都没有运行或驱动没有安装,那么按照下面的配置步骤操作即可:
1.尝试在cmd中使用此命令:net start vmx86
2.查看下%systemroot%\system32\drivers\vmx86.sys 此文件是否存在?
3.如果以上两个步骤出错 尝试从新安装vmx86驱动:步骤如下:首先开一个CMD进入vmware安装目录使用 "vnetlib -- install vmx86"命令安装vmx86驱动,
然后重启机器,在试一下。
如果直接install有错,可以先用"vnetlib -- uninstall vmx86"卸载vmx86然后再从新安装注册此驱动。
(启动虚拟机时,出现vmci.sys无效的句柄的处理方式如下)
对虚拟机相对应的.vmx文件进行编辑修改。
找到这一行: vmci0.present = "TRUE"
将 TRUE 改为 FALSE
vmci0.present = "FALSE"
或者 直接将这行删除。
保存此虚拟机的.vmx文件。
重新运行虚拟机。OK。
在物理机的 windows server 2008成功启动后,应该先从vmnet1与vmnet8网卡的网络连接中编辑属性,确认取消勾选“vmware bridge protocol”
然后在物理网卡(本地连接)中编辑属性 -> 安装 -> 服务 ,选择vmware安装目录下的netbridge.inf驱动,安装后勾选它,然后重启系统。
重启后,如果虚拟机的vmnet0网卡没有启动,那么打开vmware的虚拟网络编辑器,然后点击restore default,启动后会在
虚拟网卡列表中多出一项vmnet0(之前仅有vmnet1与vmnet8)然后就可以将虚拟机配置为使用桥接模式联网,分配IP参数后即可
也可以通过vmware的安装程序修复已安装的vmware,这样应该就能启动vmnet0网卡。
实际上,msinfo32列出的设备驱动列表是通过读取注册表位置 : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Service 获取的,
service项目包含了系统上所有的内核模式设备驱动程序项目与windows服务项目(前者的type子键,值为1;后者的type子键,值为10进制的32或16)
每个项目的名称表示一个内核模式设备驱动程序或者windows服务,例如,我们通过名为vmx86项目的“Description”子键的值 :“VMware Virtualization Driver.”可以了解到,
vmx86.sys 是vmware实现软件虚拟化的关键内核模式驱动程序。
4。硬件抽象层(hal.dll):是指一层特殊的代码,它把内核,设备驱动程序,windows执行体的其余部分,跟与平台相关的硬件差异(比如不同主板的差异)隔离开来。
hal.dll是一个可加载的内核模式模块,它是与硬件体系结构相关的,具体而言,对于不同处理器实现的不同I/O接口,中断控制器,以及是否具备多处理器通信机制等,其hal.dll也会有所不同。
进一步而言,例如32位windows 7自带2种hal.dll,第一个是halacpi.dll,用于实现ACPI(高级配置和电源接口)的32位处理器架构;而当运行windows 7的32位处理器是支持SMP(对称多处理器),或者32位处理器的高级配置和电源接口,支持APIC(高级可编程中断控制器)时,将使用第二种hal.dll,即halmacpi.dll ,这就是为什么32位windows 7系统自带这2种hal.dll的原因,
(为了应对早期的x86处理器不支持SMP或者APIC的情况,从而选择加载halacpi.dll),这也说明了hal.dll是与硬件体系结构密切相关的内核组件。
由于64位的windows server 2008 R2 系列是设计为运行在intel x64体系结构的处理器上的,而x64处理器实现了“支持高级配置和电源管理的高级可编程中断控制器”,而且又支持SMP,因此运行在x64处理器上的64位windows就只有一种硬件抽象层文件,即hal.dll
在windbg调试内核时,首先以命令 “.reload”确保加载了当前运行的内核映像对应的符号文件,然后执行命令“lm vm hal”,即可显示当前内核加载并运行的hal.dll类型。
5。窗口和图形系统:实现了图形用户界面功能(更为人们熟知的叫法是windows user 和 GDI 两部分功能),比如对窗口的处理,用户界面控件,以及绘制等。
********************************
********************************
杂项知识点:(各项前后基本独立,没有较强的逻辑相关性,但是对于了解操作系统的整体架构依然很有帮助)
处理器执行指令的速度显然受存储周期(从存储器中读一个4字节的双字到处理器,或者从处理器写一个双字到存储器中所花的时间)的限制。
近年来,处理器速度的提高一直快于存储器访问速度的提高,理想情况下,内存的构造技术可以采用与处理器中寄存器相同的构造技术,这样内存的存储周期才能跟得上处理器的指令周期甚至时钟周期,但这样做的成本太高,解决办法是在处理器与内存之间提供一个容量比内存小,比寄存器大;速度比内存快,比寄存器慢的“高速缓冲存储器”(简称高速缓存)
当处理器试图读取内存中的一个字节(或字,或双字)时,首先检查这个字节是否在高速缓存中,如果是,称为缓存命中,该字节从高速缓存传送至处理器;如果不是,称为缓存未命中,则该字节所属的“内存块”整体被读入高速缓存,然后该字节从高速缓存传送至处理器。这种做法还有一个优点:由于访问局部性现象的存在,当一个内存块被读入高速缓存以满足一次内存访问时,处理器后续要访问的数据多数情况都位于已在高速缓存中的那个内存块里。
为了方便数据在内存与高速缓存之间的传送,传送以内存块为单位,假设内存由1000个内存块组成,每个块大小为32字节(可容纳8个双字),那么高速缓存可能由10个“高速缓存行”组成,但是每个行大小必须与内存块大小相同,也能容纳8个双字。由此即可保证一个内存块中的数据与一个高速缓存行中的数据长度一致。
从上例中不难看出,在任何情况下,1000个内存块中,必定有10个内存块的数据在10个高速缓存行中保留相应的副本,另外,由于内存块的数量大于高速缓存行的数量,因此一个高速缓存行中的数据不可能用永久保留特定内存块的副本,它的内容是动态变化的,在每个高速缓存行的起始(高位)地址处用一个占特定“比特数”的标签,来标识该“行”当前存储的是哪个“块”的副本。
再举个实际的例子:在第四代(haswell架构)Intel Core I5-4440 CPU 中,一个封装的硅芯片上包括了4个物理核心,
每个核心都有各自独立的一级数据缓存与一级指令缓存,两者的总体大小均为32K字节,行大小为64字节,因此有500个高速缓存行,可以存储任意500个内存块的副本。
每个核心都有指令与数据共享的二级缓存,其大小为256K字节,行大小为64字节,因此二级缓存有4000个高速缓存行,可以存储任意4000个内存块的副本。
4个核心共享大小为6M字节的三级缓存,行大小为64字节,因此三级缓存有93750个高速缓存行,可以存储任意93750个内存块的副本。
如下图:
从上面的现实例子可以看出,每个内存块的大小肯定就是64字节(可容纳16个双字),因为三个级别的高速缓存行大小都保持为64字节,
因此,即便处理器每次只读取1个字节的指令或数据,实际在高速缓存以及内存之间传送的数据量为64字节甚至可能更多。
再者,以当前PC市场上,容量为4G字节的销售主流内存为例,其包含62500000个内存块,换言之,即便是三级缓存,也只能容纳62500000个内存块中的93750个内存块副本,“容纳率”为0.0015。
最后,我们看到一级缓存的合理大小应该为数万字节,二级的合理大小为数十万字节,三级的合理大小为数百万字节(作为对比,4GB内存的大小为40亿字节)
高速缓存的设计中要考虑的问题可以归纳为:高速缓存的总体大小,每个行的大小(需要与内存块同步),映射函数,替换算法,以及写策略。
前两个设计问题已经在上文中描述了,下面重点考察后三个设计问题。
当一个新的内存块被读入高速缓存中时,由映射函数确定这个块将占据哪个高速缓存行。这会导致至少有一个旧的高速缓存行被新块中的数据或指令替换。映射函数应该确保被替换出高速缓存行的旧内存块数据或指令在后续一段时间内不会被处理器使用,否则替换就没有意义了。如果所有的高速缓存行都已经满了,映射函数的替换算法负责找出最近一段时间内,最少被处理器访问的行,然后将这个行的内容替换成新的等长度的内存块内容,称为“最近最少使用”替换算法。这样就让被替换出高速缓存的旧块在后续一段时间内,被处理器访问的几率降到最低。
如果某个高速缓存行的内容被修改(即被处理器写入新数据),则需要在它被新的内存块取代之前,将还未写入至内存的数据写入。写策略规定何时进行写入内存的操作。
第一种“极端主动”的情况是,只要有行被处理器更新写入,就立即同步写入内存;
第二种“极端被动”的情况是,直到某个或某些行内容即将被新的内存块替换(从内存中读入)的时候,才将早先被处理器更新写入的行写入内存。
后者可以看作是高速缓存异步写入内存,虽然它减少了写入内存的次数,但是由于数据没有即时在处理器—高速缓存—内存之间同步,这会造成多处理器平台(SMP)上的内存访问以及I/O设备的DMA(直接内存访问)正确性出现问题,这两者可能会访问到“过时”的内存数据从而导致系统错误。
实际情景分析1:
一台计算机包括高速缓存,内存,一个用作虚拟内存的磁盘。
如果需要访问的“字”在高速缓存中,访问需要15纳秒;
如果该字在内存中,首先把它载入高速缓存需要45纳秒(包括初始检查该字是否在高速缓存中所用的时间),然后再从高速缓存中访问,因此总访问时间为60纳秒
如果该字不在内存中,需要10毫秒从磁盘中取出该字到内存,从内存复制该字到高速缓存需要45纳秒,然后然后再从高速缓存中访问;
因此总访问时间为10*1000*1000 + 60 = 10000060纳秒 =10.0000006毫秒;
实际情景分析2:
处理器的时钟周期,时钟频率,指令执行速度(MIPS,每秒百万条指令)之间的换算:
假设一个32位微处理器,有一个16位外部数据总线,并由一个8MHz的输入时钟驱动,总线周期的最大持续时间为时钟周期的4倍,则
1。处理器的时钟周期为 1/8MHz = 125纳秒,也就是说,该处理器的1个时钟周期为125纳秒。
2。时钟频率即为 8MHz
3。假设该处理器每个时钟周期可以执行一条指令,换言之,每125纳秒可以执行一条指令,那么一秒内可以执行 (1000*1000*1000) / 125 = 8百万条指令,也就是 8MIPS
4。数据总线的周期为处理器时钟周期的4倍,换言之,数据总线每 125*4 = 500纳秒传送 16 / 8 =2字节的数据,那么一秒内可以传送 2 * [(1000*1000*1000) / 500] = 4百万字节 = 4MBytes 的数据。
问题:如果分别将外部数据总线的位数加倍,以及外部时钟频率加倍,那么计算机系统中,其它需要改进的位置?
时钟频率加倍意味着需要采用新的芯片制造技术(假设每条指令花费相同的时钟周期);将外部数据总线的位数加倍意味着更大带宽的芯片上数据总线驱动/锁存器,以及需要对总线控制逻辑进行修改。
如果将处理器的外部时钟频率加倍(速度更快),那么内存芯片的访问速度也大致需要加倍,才不至于减慢微处理器的整体性能;
如果将外部数据总线的位数加倍,那么内存中的“字长”(一个存储单元可存储的数据位数)需要加倍,才能向数据总线发送或者从数据总线接收32位数据。
********************************