首页| 行业标准| 论文文档| 电子资料| 图纸模型
购买积分 购买会员 激活码充值

您现在的位置是:团子下载站 > 其他 > 《编程高手箴言》经典下载

《编程高手箴言》经典下载

  • 资源大小:500
  • 上传时间:2021-11-11
  • 下载次数:0次
  • 浏览次数:153次
  • 资源积分:1积分
  • 标      签: 编程

资 源 简 介

资料详情 《编程高手箴言》经典.rar 按Intel的定义,0~32个中断是CPU出错用的,称为异常。32~255是给系统自己定义使用的。在DOS中,系统使用被分成了两个部分,一个部分是硬件的IRQ,IRQ就是级连的中断控制器。其他的则被分配给软件使用。现在64位的CPU中,中断扩充成16位,则理论上可有64KB个中断。 80286芯片能在实模式和保护模式两种方式下工作。在实模式下,80286与8086芯片一样,与操作系统DOS和绝大部分硬件系统兼容;在保护模式下,每个同时运行的程序都在分开的空间内独自运行。286的保护模式还是有很多不兼容缺陷,到了386才算有真正的改革,操作系统才真正进一步发挥作用,从16位真正跨入32位程序。 2.3  32位微处理器1985年,真正的32位微处理器80386DX诞生,为32位软件的开发提供了广阔的舞台。1989年,Intel推出80486芯片,把387的浮点运算器合于486之中,并且采用流水线技术,令CPU每个周期可以执行一条指令,速度上突破100 MHz,超过了RISC的CPU。1992年,Intel发布奔腾芯片,采用多流水线技术及并行执行的能力,从此,CPU可以每个周期执行多个指令。1995年的奔腾Pro能力上再进了一步,产生动态执行技术,使CPU可以乱序执行。我们知道,从80386开始到现在的P4的CPU,它们的体系结构一直都是相同的,增加的只是内部的实现方式,所以,这些体系结构对大多数程序员来说就是透明的。 2.3.1  寄存器组成80386寄存器的宽度大多是32位,可分为如下几组:通用寄存器、段寄存器、指令指针及标志寄存器、系统地址寄存器、调试寄存器、控制寄存器和测试寄存器。应用程序主要使用前面三组寄存器,只有系统才会使用其他寄存器。这些寄存器是8080、8086、80286寄存器的超集,所以,80386包含了先前处理器的全部16位寄存器。80386的部分寄存器如图2.6所示。   第3章 Windows运行机理 3.5 PE结构分析(3)     8. .reloc节 .reloc节容纳了一个基址重定位的表。基址重定位是对指令或初始化过的变量值的一个调整;如果装载器不能把EXE或DLL文件装到连接器假定它应该放置的地址上时,则该文件需要做这个调整。如果装载器能把映像装到连接器预先确定的基地址上,则装载器将忽略该节中的重定位信息。 如果你想要进行一个选择,并且希望装载器能够总把映像装到假定的基地址上,可使用/FIXED选项来告诉连接器除去这个信息。尽管这样可在可执行文件中节省空间,但它可能使该可执行文件不能在别的Win32平台上运行。例如,假设你建立了一个NT下的EXE文件,并把该EXE基址定到0x10000处。如果你告诉连接器除去重定位信息,则该EXE将不能在95下运行,因为在95下,地址0x10000不是有效的(在95中,最小的装载地址是0x400000,即4MB)。 注意被编辑器产生的JMP和CALL指令用的是相对于其指令的偏移量,而不是在32位段中的实际偏移量。假如映像需要装载到与连接器所指定的基地址不同的位置上,这些指令也不需改变,因为他们用的是相对地址。如果需要重定位的并没有像你想像得那么多,通常只有使用了对某些数据的32位偏移量的指令才需要重定位。例如,假如有如下的全局变量声明: int         Addr; int         *ptr=& Addr; 如果连接器给映像指定的基址是0x10000,则变量Addr的地址结构是含像0x12004之类的值。在存指针ptr的内存处,连接器将写值0x12004,因为那是变量Addr的地址。如果装载器(不管是什么原因)决定在0x70000为基地址的地方装载该文件,Addr的地址则将为0x72004。然而,这样该预先初始化的ptr变量的值就不正确了,因为Addr现在在内存中比原来高了0x60000字节。 这正是重定位信息发挥作用的地方。.reloc节实际上是记录了映像中一些位置的一张表,在这些位置上,连接器所假定的装载地址和实际装载地址之间的差别需要考虑。 3.5.3  PE文件引入  我们知道函数是如何对外部DLL文件调用的。它并不是直接调DLL的函数地址,而通过CALL指令转向该可执行文件中的.text节中其他地方上的一个JMP DWORD PTR[XXXXXXXX]。作为一种选择,如果在VC中用了_ _declspec(dllimprot),则函数调用变成CALL DWORD PTR[XXXXXXXX]。在这两种情况下,JMP或CALL要查的地址存于.idata节中。JMP或CALL指令把控制传给该地址,该地址是所要求的目的地址。 在被装入内存之前,PE文件的.idata节包含了一些信息。这些信息对于装载器确定目标函数的地址并把它们拼入可执行的映像中,是必不可少的。在.idata节被装入后,它包含了一个指针,该指针指向EXE/DLL引入的函数。注意,在本节我所讨论的所有数组和结构都被包含在.idata节中。 .idata节(从文件来说可以是idata节,如果内存映射就是import table,即引入表)用一个IMAGE_IMPORT_DESCRIPTOR的数组作为开始。对于PE文件隐含连接的每个DLL,都有一个IMAGE_IMPORT _DESCRIPTOR。对于该数组,没有任何计数来指示该数组中结构的数目,数组的最后一个元素是通过在最后域中填入NULL的一个IMAGE_IMPORT_DESCRIPTOR来表示的。一个IMAGE_IMPORT_ DESCRIPTOR的格式如下: typedef struct _IMAGE_IMPORT_DESCRIPTOR {     union { // 0 for terminaTIng null import descriptor           DWORD   CharacterisTIcs;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)           DWORD   OriginalFirstThunk;          };      // 0 if not bound, // -1 if bound, and real dateTIme stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT //(new BIND) O.W. date/TIme stamp of DLL bound to (Old BIND)     DWORD   TimeDateStamp;               // -1 if no forwarders DWORD   ForwarderChain;              DWORD   Name; // RVA to IAT (if bound this IAT has actual addresses) DWORD   FirstThunk;                  } IMAGE_IMPORT_DESCRIPTOR; typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED Ø         Characteristics/OriginalFirstThunk:该域是相对的一个偏移量(RVA)。它指向一个IMAGE_THUNK_DATA类型的数据。其中,每个IMAGE_THUNK_DATA DWORD对应一个被该EXE/DLL引入的函数。 Ø         TimeDataStamp:表示该时间/日期印记指示文件是什么时间建立的。该域一般为0。 Ø         ForwarderChain:该域与传递相关联,包括一个DLL把对它的一个函数的访问传递给另一个DLL。例如,在Windows中,KERNEL32.DLL把它的一些引出函数传递给NTDLL.DLL,一个应用程序或许认为它调用了KERNEL32.DLL中的一个函数,但实际上它的调用进入到了NTDLL.DLL中。该域把一个索引含到FirstThunk数组中,被该域索引过的函数将被传递给另一个DLL。 Ø         Name:这是相对一个用null作为结束符的ASCII字符串的一个RVA,该字符串含的是该引入DLL文件的名字(例如,KERNEL32.DLL或者USER32.DLL)。 Ø         PIMAGE_THUNK_DATA FirstThunk:      该域是相对一个PIMAGE_THUNK_DATA DWORD数组的一个偏移量(RVA)。大多数情况下,该DWORD被解释成指向一个IMAGE_IMPORT_ BYNAME结构的一个指针。然而,也有可能用顺序值引入一个函数。 一个IMAGE_IMPORT_DESCRIPTOR的重要部分是引入DLL的名字和两个IMAGE_THUNK_DATA DWORD数组。每个IMAGE_THUNK_ DATA DWORD对应一个引入函数。在EXE文件中,这两个数组(被Characteristics和FirstThunk域所指向)并行地运行,并且都是在尾端处以一个NULL指针项作为中止。 为什么会有两个并行的指向IMAGE_THUNK_DATA结构的指针数组呢? 第一个数组(被Characteristics指向的那一个)被单独留下,并且绝不会被修改,它有时也被称做提示名称表(hint-name table)。 第二个数组(被IMAGE_IMPORT_DESCRIPTOR的FirstThunk域所指向)被PE装载器改写,然后用该引入函数的地址来改写IMAGE_ THUNK_DATA DWORD的值。
VIP VIP