
第8章内存管理机制与TC编译模式.ppt
23页2024/9/31第八章第八章 内存管理机制内存管理机制与与TC编译模式编译模式Ø寄存器和伪变量寄存器和伪变量Ø内存的寻址模式内存的寻址模式ØTC的编译模式的编译模式2024/9/32第一节第一节 寄存器和伪变量寄存器和伪变量Ø寄存器是寄存器是CPU中的部件,用中的部件,用来存储数据、地址和指令来存储数据、地址和指令Ø8086、、8088、、80286的的CPU只有只有14个寄存器,都是个寄存器,都是16位位寄存器寄存器Ø其中其中AX、、BX、、CX、、DX每每个都可以分为两个个都可以分为两个8位寄存位寄存器来使用器来使用2024/9/33Ø80386之后的之后的CPU对前十个寄存器做了扩充(对前十个寄存器做了扩充(32位),位),同时又增加了两个寄存器同时又增加了两个寄存器FS和和GS,如图所示:,如图所示:ØTC只支持只支持14个寄存器且认为它们都是个寄存器且认为它们都是16位的位的2024/9/34Ø程序中,有时候需要操作这些寄存器,为了能在程序中,有时候需要操作这些寄存器,为了能在TC中中使用它们,使用它们,TC定义了一些定义了一些伪变量伪变量以对应相应的寄存器:以对应相应的寄存器:_AX: 对应寄存器对应寄存器AX_AH: 对应寄存器对应寄存器AH_AL: 对应寄存器对应寄存器AL_BX: 对应寄存器对应寄存器BX_BH: 对应寄存器对应寄存器BH_BL: 对应寄存器对应寄存器BL_CX: 对应寄存器对应寄存器CX……Ø例如:例如:若要将若要将字符字符‘ A’置于置于AL中,则可用中,则可用 ::_AL = ‘A’;;若要将整数若要将整数100置于置于AX中,则可用:中,则可用:_AX = 100;2024/9/35第二节第二节 内存的寻址模式内存的寻址模式Ø实模式寻址实模式寻址Ø保护模式寻址保护模式寻址Ø默认的段寄存器默认的段寄存器Ø近程指针与远程指针近程指针与远程指针Ø与地址操作有关的几个函数(宏)与地址操作有关的几个函数(宏)2024/9/36一、内存的实模式一、内存的实模式Ø8086、、8088、、80286的的CPU都是都是16位的。
对应的数位的对应的数据总线、地址总线、控制总线也据总线、地址总线、控制总线也“应应”是是16位Ø但但16位的地址总线只能寻址位的地址总线只能寻址65536个内存单元个内存单元(64K),显然太小了显然太小了Ø当时认为寻址能力达到当时认为寻址能力达到1M就够用了,故将地址总就够用了,故将地址总线设定成了线设定成了20位Ø20位的地址不便用位的地址不便用16位的位的CPU处理,因此当时采用处理,因此当时采用了一种将内存分段的方法,来解决这个问题了一种将内存分段的方法,来解决这个问题2024/9/37Ø从内存的任意一个从内存的任意一个“地址能被地址能被16整除整除”的单元开始,将该单元之的单元开始,将该单元之后的共后的共64K内存划为一个内存划为一个“段段”Ø之所以要求段的起点必须是之所以要求段的起点必须是16的的倍数,是为了把段的首地址存入倍数,是为了把段的首地址存入段寄存器中(只能存段寄存器中(只能存16位)位)Ø在一个段内,任意单元的地址都在一个段内,任意单元的地址都可以用一个相对于段起点的地址可以用一个相对于段起点的地址来表示,称作偏移地址,偏移地来表示,称作偏移地址,偏移地址是一个址是一个16位的无符号整数。
位的无符号整数00000H00010H00020H00030H00040H00050H…….每16Bytes为1小段64K Bytes2024/9/38Ø如图:段的起始地址是如图:段的起始地址是00030H, 则段寄存器中存储则段寄存器中存储 的是的是0003H,图图中中00072单元的偏移地址是单元的偏移地址是0042HØ段内任意单元的地址都可以表示段内任意单元的地址都可以表示成成“段地址段地址:偏移地址偏移地址”的形式的形式,,00072单元的地址可表示为:单元的地址可表示为:0003:0042Ø段与段可以重叠,如图所示段与段可以重叠,如图所示Ø另一段的基址另一段的基址00050H,此时,此时00072H的地址又可表示为:的地址又可表示为:0005:0022 00030H00031H00032H00033H00034H…….64K Bytes00072H00050H64K Bytes2024/9/39Ø可见,同一个物理地址可有多可见,同一个物理地址可有多种不同的表示法种不同的表示法Ø采用这种分段的方式使寻址能采用这种分段的方式使寻址能力达到了力达到了1M,但是这种寻址,但是这种寻址方式缺乏对内存的有效保护方式缺乏对内存的有效保护Ø为了区别后来的保护模式,将为了区别后来的保护模式,将上述内存分段寻址的方式称作上述内存分段寻址的方式称作实地址模式实地址模式或或内存的内存的实模式实模式。
00030H00031H00032H00033H00034H…….64K Bytes00072H00050H64K Bytes2024/9/310二、内存的保护模式二、内存的保护模式Ø为了保护内存,需要记录段的首地址、段长度、段为了保护内存,需要记录段的首地址、段长度、段的访问权限等信息,这些信息合起来是一个的访问权限等信息,这些信息合起来是一个64位的位的数据结构数据结构---段描述符段描述符Ø显然,段寄存器存储不下这个段描述符显然,段寄存器存储不下这个段描述符Ø解决方法:解决方法:Ø在内存中开辟一段区域,按顺序存储所有段的段在内存中开辟一段区域,按顺序存储所有段的段描述符,组成一个描述符,组成一个段描述符表段描述符表Ø段寄存器中只存储段描述符的索引(段选择子)段寄存器中只存储段描述符的索引(段选择子)2024/9/311三、默认的段寄存器三、默认的段寄存器ØCS: 总是存储代码段的基址总是存储代码段的基址ØDS: 总是存储数据段的基址总是存储数据段的基址ØES: 总是存储附加段的基址总是存储附加段的基址ØSS: 总是存储堆栈段的基址总是存储堆栈段的基址2024/9/312四、近程指针和远程指针四、近程指针和远程指针Ø近程指针近程指针是一个是一个16位的指针,用来在段内位的指针,用来在段内寻址。
寻址Ø近程指针在定义时,使用近程指针在定义时,使用near关键字说明关键字说明(可以省略)(可以省略)如:如:int near *p; //或或 int *p;p用于在数据段内寻址,用于在数据段内寻址,p存储的是数据段内的偏存储的是数据段内的偏移地址,而数据段的首址固定在移地址,而数据段的首址固定在DS中中2024/9/313四、近程指针和远程指针四、近程指针和远程指针Ø近程指针的最大值只能到近程指针的最大值只能到0xffff,即,即65535,,超过将出错超过将出错如:如:char near *p;p = (char near *)0xffff;p++;printf(“%p\n”, p); // %p是用十六进制输出地址是用十六进制输出地址其其运行结果是运行结果是::0000因为因为65535加加1将产生进位(丢弃),使将产生进位(丢弃),使p的的16位都位都是是0这种现象称作折回这种现象称作折回2024/9/314四、近程指针和远程指针四、近程指针和远程指针Ø远远程指针程指针是一个是一个32位的指针,用来寻址不同的段位的指针,用来寻址不同的段其中高位的两个字节存储段值,低位的两个字节存其中高位的两个字节存储段值,低位的两个字节存储偏移地址。
储偏移地址Ø由于远程指针对应的数据可以在不同的段,故数据由于远程指针对应的数据可以在不同的段,故数据段寄存器中的段基址可能会发生改变段寄存器中的段基址可能会发生改变Ø远程指针定义时用远程指针定义时用far说明,如:说明,如:char far *p;p = (char far*)0x2A000002;Ø对远程指针加减运算,只对偏移地址进行,段地址对远程指针加减运算,只对偏移地址进行,段地址不参与运算,不参与运算,故故也会发生折回现象也会发生折回现象2024/9/315四、近程指针和远程指针四、近程指针和远程指针Ø对于同一个物理地址,用对于同一个物理地址,用“段地址段地址:偏移地址偏移地址”的方的方式表示时,可以有若干种形式,如物理地址式表示时,可以有若干种形式,如物理地址1234H可可以表示为:以表示为:0000:1234, 0001:1224, 0002:1214, ……Ø虽然这些地址表示的是同一物理地址,但如果对它虽然这些地址表示的是同一物理地址,但如果对它们进行比较,得出的结果是不相等们进行比较,得出的结果是不相等 设设远程指针远程指针p1、、p2存储的是同一物理地址,但段地存储的是同一物理地址,但段地址和偏移地址不同,则表达式址和偏移地址不同,则表达式p1== p2的值为的值为0。
因因为计算机是直接比较两个指针变量中的为计算机是直接比较两个指针变量中的32位二进制位二进制数,而不是转化为物理地址后再比较数,而不是转化为物理地址后再比较2024/9/316五、与地址操作有关的几个函数五、与地址操作有关的几个函数ØTC在在dos.h中定义了几个函数(实际是宏),中定义了几个函数(实际是宏),用来处理段地址或偏移地址用来处理段地址或偏移地址1.FP_SEG2.FP_OFF3.MK_FP4.peekb和和peek5.pokeb和和poke2024/9/317五、与地址操作有关的几个函数五、与地址操作有关的几个函数1、、FP_SEGØ功功 能:获取远地址中的段值能:获取远地址中的段值Ø原型:原型:unsigned FP_SEG(void far *farptr); 例例8.1 #include
功能:由段值和偏移地址组成一个远程指针Ø原型:原型:void far *MK_FP(unsigned seg, unsigned off);例例8.3 (主要程序段):(主要程序段): char far *p; unsigned seg, off; p = MK_FP(0xb000, 0x20); seg = FP_SEG(p); off = FP_OFF(p); printf(“far p:%Fp,seg:%04X,off:%04X\n”, p,seg,off); 2024/9/320五、与地址操作有关的几个函数五、与地址操作有关的几个函数Ø4、、peekb和和peekØ功能:从给定的地址读取一个字节或一个字功能:从给定的地址读取一个字节或一个字Ø原型:原型: char peekb(unsigned seg, unsigned off); int peek(unsigned seg, unsigned off);例如:例如: char c, s[]="hello"; c=peekb(_DS, s); printf("%c\n", c);输出结果是:输出结果是:h 2024/9/321五、与地址操作有关的几个函数五、与地址操作有关的几个函数Ø5、、pokeb和和pokeØ功能:向指定的位置写一个字节或一个字功能:向指定的位置写一个字节或一个字Ø原型:原型:void pokeb(unsigned seg, unsigned off, char value);void poke (unsigned seg, unsigned off, int value);例如:例如:char s[10];int a=0x0041;poke(_DS, s, a);printf(“%s\n”, s);输出结果是:输出结果是:A 2024/9/322第三节第三节 TC的编译模式的编译模式Ø微模式微模式(Tiny)Ø小模式小模式(Small) Ø中模式中模式(Medium) Ø紧凑模式紧凑模式(Compact)Ø大模式大模式(Large)Ø巨模式巨模式(Huge)2024/9/323问问 题题Ø若要使寄存器若要使寄存器AX存储存储3,,C中应如何表达?中应如何表达?Ø实地址模式如何寻址?实地址模式如何寻址?Ø常用的段寄存器有哪些?分别存储什么?常用的段寄存器有哪些?分别存储什么?Ø什么是近程指针、远程指针?如何定义?使用时什么是近程指针、远程指针?如何定义?使用时注意什么?注意什么?Ø如何从一个远程指针分离出段地址和偏移地址?如何从一个远程指针分离出段地址和偏移地址?Ø如何由段地址和偏移地址得到一个远程指针?如何由段地址和偏移地址得到一个远程指针?ØTC的编译模式有哪些?适用于什么情况?的编译模式有哪些?适用于什么情况?。
