从实模式到保护模式第8到12章笔记_第1页
从实模式到保护模式第8到12章笔记_第2页
从实模式到保护模式第8到12章笔记_第3页
从实模式到保护模式第8到12章笔记_第4页
从实模式到保护模式第8到12章笔记_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第10章 IA3210.1 IA-32架构的基本执行环境 10.1.1 寄存器的扩展 在16位处理器内,有8个通用寄存器AX、BX、CX、DX、SI、DI、BP和SP,其中,前4个还可以拆分成两个独立的8位寄存器来用,即AH、AL、BH、BL、CH、CL、DH和DL。为了在汇编语言程序中使用经过扩展(Extend)的寄存器,需要给它们命名,它们的名字分别是EAX、EBX、ECX、EDX、ESI、EDI、ESP和EBP。可以在程序中使用这些寄存器,即使是在实模式下: mov eax,0xf0000005 mov ecx,eax add edx,ecx 但是,就像以上指令所示的那样,指令的源操作数

2、和目的操作数必须具有相同的长度,个别特殊用途的指令除外。因此,像这样的搭配是不允许的,在程序编译时,编译器会报告错误: mov eax,cx ;错误的汇编语言指令 如果目的操作数是32位寄存器,源操作数是立即数,那么,立即数被视为32位的: mov eax,0xf5 ;EAX0x000000f5 32位通用寄存器的高16位是不可独立使用的,但低16位保持同16位处理器的兼容性。因此,在任何时候它们都可以照往常一样使用: mov ah,0x02 mov al,0x03 add ax,si 可以在32位处理器上运行16位处理器上的软件。但是,它并不是16位处理器的简单增强。事实上,32位处理器有自

3、己的32位工作模式,在本书中,32位模式特指32位保护模式。在这种模式下,可以完全、充分地发挥处理器的性能。同时,在这种模式下,处理器可以使用它全部的32根地址线,能够访问4GB内存。10.1.2 基本的工作模式 8086具有16位的段寄存器、指令指针寄存器和通用寄存器(CS、SS、DS、ES、IP、AX、BX、CX、DX、SI、DI、BP、SP),因此,我们称它为16位的处理器。尽管它可以访问1MB的内存,但是只能分段进行,而且由于只能使用16位的段内偏移量,故段的长度最大只能是64KB。8086只有一种工作模式,即实模式。当然,这个名称是后来才提出来的。 10.1.3 线性地址 为IA-3

4、2处理器编程,访问内存时,需要在程序中给出段地址和偏移量,因为分段是IA-32架构的基本特征之一。传统上,段地址和偏移地址称为逻辑地址,偏移地址叫做有效地址(Effective Address,EA),在指令中给出有效地址的方式叫做寻址方式(Addressing Mode)。10.2 现代处理器的结构和特点 10.2.1 流水线 处理器的每一次更新换代,都会增加若干新特性,这是很自然的。同时我们也会发现,老软件在新的处理器上跑得更快。这里面的原因很简单,处理器的设计者总是在想尽办法加快指令的执行。 10.2.2 高速缓存 影响处理器速度的另一个因素是存储器。从处理器内部向外看,它们分别是寄存器

5、、内存和硬盘。当然,现在有的计算机已经用上了固态磁盘。 10.2.3 乱序执行 为了实现流水线技术,需要将指令拆分成更小的可独立执行部分,即拆分成微操作(Micro-Operations),简写为ops。 10.2.5 分支目标预测 流水线并不是百分之百完美的解决方案。实际上,有很多潜在的因素会使得流水线不能达到最佳的效率。一个典型的情况是,如果遇到一条转移指令,则后面那些已经进入流水线的指令就都无效了。换句话说,我们必须清空(Flush)流水线,从要转移到的目标位置处重新取指令放入流水线。 10.3.1 32位处理器的寻址方式 在16位处理器上,指令中的操作数可以是8位或者16位的寄存器、指

6、向8位或者16位实际操作数的16位内存地址,以及8位或16位的立即数。 第十一章 进入保护模式NASM编译l 情景描述使用NASM编译一段程序,并可以在裸机上运行。l 实现功能在开机后显示"Hello, OS world!"l 流程1) 初始化寄存器2) 调用BIOS int 10h,显示字符串3) 进入死循环l 代码及注释%define_BOOT_DEBUG_%ifdef_BOOT_DEBUG_org 0100h%elseorg 07c00h%endif;告诉编译器加载到0100处生成,这样方便生成com文件。;或者告诉编译器加载到7c00处生成,这样方便mov ax,c

7、s;将当前段地址放入ax,可以不要mov ds,ax;将当前段地址放入数据寄存器,可以不要mov es,ax;将当前段地址放入extra寄存器,可以不要call DispStr;调用显示字符串程序jmp $;无限循环(跳转到当前地址)DispStr:mov ax,BootMessage;BootMessage的首地址送axmov bp,ax; 段内地址送到bp,至此地址完成 CS:BP = 串地址mov cx,16; CX = 串长度mov ax,01301h; AH = 13,AL = 01hmov bx,000ch; BH = 0(页号为0),BL = 0ch(黑底红字高亮)mov dl,

8、0; 0送dx寄存器的低字节int 10h; 10h号中断(视频中断,对应的中断向量为40-43H)ret; 从显示子程序中返回到主程序BootMessage: db "Hello, OS world!"times 510-($-$) db 0; 用“0”填充0面0磁道1扇区剩下的空间,使生成的二进制代码恰好为512字节;;$是当前行的段内偏移地址,$是本小节代码的第一行代码,在本程序中就是“org07c00h”的段内偏移地址。dw 0xaa55;结束标志. 使得0面0磁道1扇区510字节存55,511字节存aa,0扇区从0-511号单元,共512个字节。(引导扇区的结束标

9、志)l 显示界面运行程序界面实验补充资料一. 内存引导地址7C00Intel公司当初设计8086系统内存时对内存(1M)是这样规定的:内存包括暂驻程序区640K和系统内存区384K,在640K中把BIOS和驻留操作系统的数据和程序安排在低地址处,在保留一定的可扩展空间后,为配合BIOS和磁盘操作系统就把7C00规定为硬件及软件都支持的启动引导的内存地址,并写成引导规范。在当时各个公司都有自己的一些未公开的标准,而IBM公开推行IBM计算机的内部详细的结构时,他采用的是Intel的芯片,所以他遵循了这个标准,又由于大批的公司知道了这个标准之后,都兼容这个标准,以后也继续兼容,就真正成为一个共同的

10、标准了,现在的CPU都是向下兼容的,还在用7C00。由于引导扇区被加载到了7c00h处,代码中BootMessage的首地址放入bp中时,只是将8位放入了bp,缺省了高8位,这高8位需要由org指定,否则无法将正确的字符串相对偏移地址放入bp中:BootMessage变量对应字符串在内存中首地址=0000(es段值):7c00(org指定)+BootMessage在程序段内偏移(8位2进制)org会在编译期影响到内存寻址指令的编译(编译器会把所有程序用到的段内偏移地址自动加上org 后跟的数值),而其自身并不会被编译成机器码。就是为程序中所有的引用地址(需要计算的相对地址)增加一个段内偏移值。

11、二. 10h中断说明10h中断表示,功能号为AH=13h时为写入字符串;AL=01h表示字符串包含属性;BH=页数;BL=显示属性;CX=字符串中的字符数量;DL,DH=从哪一列,行开始写;ES:BP指向该字符串 反编译通过反编译,可以将程序返回至源代码内容反编译方法:ndisasmw -o 0x7c00 >> 1.asm显示1.asm内容如下:00007C00 8CC8 mov ax,cs00007C02 8ED8 mov ds,ax00007C04 8EC0 mov es,ax00007C06 E80200 call 0x7c0b00007C09 EBFE jmp short

12、0x7c0900007C0B B81E01 mov ax,0x11e00007C0E 89C5 mov bp,ax00007C10 B91000 mov cx,0x1000007C13 B80113 mov ax,0x130100007C16 BB0C00 mov bx,0xc00007C19 B200 mov dl,0x000007C1B CD10 int 0x1000007C1D C3 ret以下为数据区00007C1E 48 H00007C1F 65 e00007C206Cl00007C21 6Cl00007C22 6Fo00007C23 2C ,00007C2420空格00007C25

13、 4FO00007C26 53S00007C27 20空格00007C2877w00007C296F000007C2A 72r00007C2B6Cl00007C2C 64d00007C2D 21!以下数据为000007C2E 00无00007DFC 00 无00007DFD 00无00007DFE55AA 55AA 保护模式 保护模式介绍保护模式(Protected Mode,或有时简写为pmode) 是一种80286系列和之后的x86兼容CPU操作模式。保护模式有一些新的特色,设计用来增强多工和系统稳定度,像是内存保护,分页系统,以及硬件支援的虚拟内存。大部分的现今x86操作系统都在保护模式

14、下运行,包含Linux、FreeBSD、以及微软Windows 2.0 和之后版本。PM是处理器的native模式,在这种模式下,处理器支持所有的指令和所有的体系结构特性提供最高的性能和兼容性。对于所有的应用程序和操作系统来说,建议都使用这种模式。另外一种286和其之后CPU的操作模式是真实模式(Real Mode),一种向前兼容且关闭这些特色的模式。设计用来让新的芯片可以执行旧的软件。依照设计的规格,所有的x86 CPU都是在真实模式下开机来确保传统操作系统的向前兼容性。在任何保护模式的特色可用前,他们必须要由某些程序手动地切换到保护模式。在现今的电脑,这种切换通常是由操作系统在开机时候必须

15、完成的第一件工作的其中内容之一。为了保证PM的兼容性,处理器允许在受保护的,多任务的环境下执行RM程序。这个特性被称做虚拟8086模式(Virtual -8086 Mode),尽管它并不是一个真正的处理器模式。Virtual-8086模式实际上是一个PM的属性,任何任务都可以使用它。它也可能当CPU在保护模式下运行时,使用虚拟86模式来执行设计给真实模式的程序码。RM提供了Intel 8086处理器的编程环境,另外有一些扩展(比如切换到PM或SMM的能力)。当主机被Power-up或Reset后,处理器处于RM下。对于Intel 80386以及其后的芯片,只有使用PM才能发挥作用。因此需要解决

16、从RM切换到PM的问题。 GDT(Global Descriptor Table)在保护模式下,一个重要的数据结构就是GDT。在实模式下,我们对一个内存地址的访问是通过(Segment:Offset)的方式来进行的。其中Segment是一个段的基地址,而一个段的最大长度是64 KB(216),这是16位系统所能表示的最大长度。而Offset则是相对于该段基地址的偏移量。因此Base Address+Offset就是一个内存绝对地址。由此,我们可以看出,一个段具备两个因素:Base Address和Limit(段的最大长度),而对一个内存地址的访问,则是需要指出:使用哪个段?以及相对于这个段Ba

17、se Address的Offset(这个Offset应该小于此段的Limit)。当然对于16-bit系统,Limit不要指定,默认为最大长度64KB,而 16-bit的Offset也永远不可能大于此Limit。我们在实际编程的时候,使用16-bit段寄存器CS(Code Segment),DS(Data Segment),SS(Stack Segment)来指定Segment,CPU将段寄存器中的数值向左偏移4-bit,放到20-bit的地址线上就成为20-bit的Base Address。(因此内存为220,不会超过1M)到了保护模式,内存的管理模式分为两种,段模式和页模式,其中页模式也是基

18、于段模式的。也就是说,保护模式的内存管理模式事实上是:纯段模式和段页式。进一步说,段模式必不可少。对于段模式来讲,访问一个内存地址仍然使用Segment:Offset的方式,其中由于保护模式运行在32位系统上,那么Segment的两个因素:Base Address和Limit也都应该是32位的。IA-32允许将一个段的Base Address设为32-bit所能表示的任何值(Limit则可以被设为32-bit所能表示的,以212为倍数的任何数字。而不象Real Mode下,一个段的Base Address只能是16的倍数(因为其低4-bit是通过左移运算得来的,只能为0,从而达到使用16-bi

19、t段寄存器表示20-bit Base Address的目的),而一个段的Limit只能为固定值64 KB。)另外,Protected Mode又为段模式提供了保护机制,也就说一个段的描述符需要规定对自身的访问权限(Access)。所以在Protected Mode下,对一个段的描述则包括3方面因素:Base Address, Limit, Access,它们加在一起被放在一个64-bit长的数据结构中,被称为段描述符。这样如果直接通过一个64-bit段描述符来引用一个段的时候,就必须使用一个64-bit长的段寄存器装入这个段描述符。但Intel为了保持向后兼容,将段寄存器仍然规定为16-bit

20、(尽管每个段寄存器事实上有一个64-bit长的不可见部分,但对于程序员来说,段寄存器就是16-bit的),那么很明显,无法通过16-bit长度的段寄存器来直接引用64-bit的段描述符。解决的方法就是把这些长度为64-bit的段描述符放入一个数组中,而将段寄存器中的值作为下标索引来间接引用(事实上,是将段寄存器中的高13 -bit的内容作为索引)。这个全局的数组就是GDT。在GDT中存放的不仅仅是段描述符,还有其它描述符,它们都是64-bit。GDT可以被放在内存的任何位置,那么当程序员通过段寄存器来引用一个段描述符时,CPU必须知道GDT的入口,也就是GDT的基地址放在哪里,因此设计者提供了

21、一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过lgdt指令将GDT的入口地址装入此寄存器,之后从此以后,CPU就根据此寄存器的内容作为GDT的入口来访问GDT了。GDT是Protected Mode所必须的数据结构,也是唯一的。它是全局可见的,对任何一个任务而言都是这样。除了GDT之外,IA-32还允许程序员构建与GDT类似的数据结构,它们被称作LDT(Local Descriptor Table)。但与GDT不同的是,LDT在系统中可以存在多个,并且不是全局可见的,它们只对引用它们的任务可见。每个任务最多可以拥有一个LDT。另外,每一个LDT自身

22、作为一个段存在,它们的段描述符被放在GDT中。前面所讨论的装入段寄存器中作为GDT/LDT索引的就是Segment Selector(选择子),当需要引用一个内存地址时,使用的仍然是Segment:Offset模式,具体操作是:在相应的段寄存器装入Segment Selector,按照这个Segment Selector可以到GDT或LDT中找到相应的Segment Descriptor,这个Segment Descriptor中记录了此段的Base Address,然后加上Offset,就得到了最后的内存地址。 从实模式到保护模式l 情景描述完成一个程序,从实模式到保护模式的转变l 编译方法

23、nasm pmtest1.asm -o l pmtest1.asm程序源码%include "pm.inc" 常量, 宏, 以及一些说明org 0100h; 告诉编译器程序加载到0100处(段值) jmp LABEL_BEGIN; 跳到LABEL_BEGIN处SECTION .gdt; GDTLABEL_GDT: Descriptor 0, 0, 0 ; 空描述符(全部为零)LABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C+DA_32 ; 非一致代码段, 32(定义界限和属性); LABEL_DESC_CODE32

24、98H (10011000B) 内存中,DPL为0,代码段,只执行; LABEL_DESC_CODE32 4000H (0100B) 32位LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址(定义基址,界限和属性); LABEL_DESC_VIDEO 92h 存在的可读写数据段属性值,指向显存; GDT 结束GdtLen equ $-LABEL_GDT ; GDT长度GdtPtr dw GdtLen-1 ; GDT界限 dd 0 ; GDT基地址; GDT 选择子SelectorCode32equ LABEL_DESC_CO

25、DE32-LABEL_GDTSelectorVideo equ LABEL_DESC_VIDEO-LABEL_GDT; GDT 选择子 结束; END of SECTION .gdtSECTION .s16BITS 16LABEL_BEGIN: mov ax, cs ; 段值-AX mov ds, ax ; DS指向与CS相同的段值 mov es, ax ; ES指向与CS相同的段值 mov ss, ax ; SS指向与CS相同的段值 mov sp, 0100h ; 初始化 32 位代码段描述符 xor eax, eax ; 清空EAX mov ax, cs ; 段值 shl eax, 4 ;

26、 段值左移4位 add eax, LABEL_SEG_CODE32 ; 段值+偏移地址-基址 mov word LABEL_DESC_CODE32 + 2, ax ; 基址1 shr eax, 16 mov byte LABEL_DESC_CODE32 + 4, al; 基址2 mov byte LABEL_DESC_CODE32 + 7, ah ; 基址3 ; 为加载 GDTR 作准备 xor eax, eax ; 清空EAX mov ax, ds shl eax, 4 add eax, LABEL_GDT ; eax <- gdt 基地址 mov dword GdtPtr + 2,

27、eax ; GdtPtr + 2 <- gdt 基地址 ; 加载 GDTR lgdt GdtPtr ; GdtPtr -> lgdt ; 关中断 cli ; 打开地址线A20 in al, 92h or al, 00000010b out 92h, al ; 准备切换到保护模式,CRO第0位置置1 mov eax, cr0 or eax, 1 mov cr0, eax ; 真正进入保护模式 jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs, 并跳转到 Code32Selector:0 处; LABEL_DESC_CO

28、DE32已经准备好,其中的基址就是LABEL_SEG_CODE32地址处; END of SECTION .s16SECTION .s32; 32 位代码段. 由实模式跳入.BITS 32LABEL_SEG_CODE32: mov ax, SelectorVideo mov gs, ax ; 视频段选择子(目的) -> GS (段值) mov edi, (80 * 10 + 0) * 2 ; 屏幕第 10 行, 第 0 列。 mov ah, 0Ch ; 0000: 黑底 1100: 红字 mov al, 'P' mov gs:edi, ax ; 到此停止 jmp $Seg

29、Code32Len equ $-LABEL_SEG_CODE32; END of SECTION .s32l pm.inc工具程序; GDT参数描述符类型值说明 ; 其中: ; DA_ : Descriptor Attribute / ; D : 数据段 / ; C : 代码段 / ; S : 系统段 ; R : 只读 / ; RW : 读写 / ; A : 已访问DA_32 equ4000h; 32 位段DA_DPL0 equ00h; DPL = 0DA_DPL1 equ 20h; DPL = 1DA_DPL2 equ 40h; DPL = 2DA_DPL3 equ 60h; DPL = 3

30、; 存储段描述符类型值说明DA_DR equ90h; 存在的只读数据段类型值DA_DRW equ 92h; 存在的可读写数据段属性值DA_DRWA equ 93h; 存在的已访问可读写数据段类型值DA_C equ 98h; 存在的只执行代码段属性值DA_CR equ 9Ah; 存在的可执行可读代码段属性值 DA_CCO equ 9Ch; 存在的只执行一致代码段属性值 DA_CCOR equ 9Eh; 存在的可执行可读一致代码段属性值 ; 系统段描述符类型值说明DA_LDT equ 82h; 局部描述符表段类型值 DA_TaskGate equ 85h; 任务门类型值 DA_386TSS equ

31、 89h; 可用 386 任务状态段类型值 DA_386CGate equ 8Ch; 386 调用门类型值 DA_386IGate equ 8Eh; 386 中断门类型值 DA_386TGate equ 8Fh; 386 陷阱门类型值 ; RPL(Requested Privilege Level): 请求特权级,用于特权检查。 ; TI(Table Indicator): 引用描述符表指示位 ; TI=0 指示从全局描述符表GDT中读取描述符; ; TI=1 指示从局部描述符表LDT中读取描述符。; 选择子类型值说明 ; 其中: SA_ : Selector AttributeSA_RPL0

32、 equ 0; SA_RPL1 equ 1 ; RPLSA_RPL2 equ 2 ; SA_RPL3 equ 3 ; SA_TIG equ 0 ; TISA_TIL equ 4 ; ;定义描述符(64位); usage: Descriptor Base, Limit, Attr ; Base: dd (32位); Limit: dd(低20位可用) ; Attr: dw (高字节的低4位为0)%macro Descriptor 3 dw %2 & 0ffffh; 段界限 1 (2 字节) dw %1 & 0ffffh; 段基址 1 (2 字节) db (%1 >>

33、16) & 0ffh; 段基址 2 (1 字节) dw (%2 >> 8) & 0f00h | (%3 & 0f0ffh); 属性 1 + 段界限 2 + 属性 2 (2 字节) db (%1 >> 24) & 0ffh; 段基址 3 (1 字节)%endmacro; 共 8 字节; 代码段和数据段描述符BYTE7BYTE6BYTE5BYTE4BYTE3BYTE2BYTE1BYTE031.24段基址3属性(见下表)23.16段基址215.0段基址115.0段界限1; 属性内容7654321076543210GD/B0AVL19.16 段界

34、限2PDPLSTYPE; 属性页说明属性概括说明具体说明P存在位(Present)P=1段在内存中存在P=0段在内存中不存在DPL表示描述符特权级(Descriptor Privilege Level)它规定了段的特权级特权级范围:03S说明描述符的类型S=1数据段和代码段描述符S=0系统段描述符和门描述符TYPE描述符类型描述符类型TYPE值说明数据段描述符S=10只读1只读,已访问2读/写3读/写,已访问4只读,向下扩展5只读,向下扩展,已访问6读/写,向下扩展7读/写,向下扩展,已访问代码段描述符S=18只执行9只执行,已访问A执行/读B执行/读,已访问C只执行,一致码段D只执行,一致码

35、段,已访问E执行/读,一致码段F执行/读,一致码段,已访问系统端描述符和门描述符S=00<未定义>1可用286TSS2LDT3忙的286TSS4286调用门5任务门6286中断门7286陷阱门8<未定义>9可用386TSSA<未定义>B忙的386TSSC386调用门D<未定义>E386中断门F386陷阱门G段界限粒度位(Granularity)G=0段界限粒度为字节G=1段界限粒度为4KBD/B这一位比较复杂,分三种情况在可执行代码段描述符中,这一位叫做D位D=1默认情况下,指令使用32位地址以及32位或8位操作数D=0默认情况下,使用16位地址

36、及16位及8位操作数在向下扩展数据段的描述符中,这一位叫做B位D=1表示段的上部界限为4GBD=0表示段的上部界限为64KB在描述堆栈段的描述符中,这一位叫做B位D=1隐式的堆栈访问指令(如push、pop和call)使用32位堆栈指令寄存器espD=0隐式的堆栈访问指令(如push、pop和call)使用16位堆栈指令寄存器spAVL保留并可用位保留位,可以被系统软件使用;定义门; usage: Gate Selector, Offset, DCount, Attr ; Selector: dw ; Offset: dd ; DCount: db ; Attr: db%macro Gate

37、4 dw (%2 & 0FFFFh); 偏移 1 (2 字节) dw %1; 选择子 (2 字节) dw (%3 & 1Fh)|(%4<<8)&0FF00h); 属性 (2 字节) dw (%2>>16)&0FFFFh); 偏移 2 (2 字节)%endmacro ; 共 8 字节关于c11_mbr.asm的进阶说明一. 显示结果:第十行第0列打印一个红色的P,如图12-2所示。二. GDT进阶说明GDT是Protected Mode所必须的数据结构,那么在进入Protected Mode之前,必须设定好GDT,并通过LGDT将其装入相应

38、的寄存器。尽管GDT允许被放在内存的任何位置,但由于GDT中的元素描述符都是64-bit长,也就是说都是8个字节,所以为了让CPU对GDT的访问速度达到最快,应该将GDT的入口地址放在以8个字节对齐,也就是说是8的倍数的地址位置。GDT中第一个描述符必须是一个空描述符,也就是它的内容应该全部为0。如果引用这个描述符进行内存访问,则产生General Protection异常。如果一个OS不使用虚拟内存,段模式会是一个不错的选择。但现代OS没有不使用虚拟内存的,而实现虚拟内存的比较方便和有效的内存管理方式是页式管理。在IA-32上如果我们想使用页式管理,我们只能使用段页式没有方法可以完全禁止段模式。但我们可以尽力让段的效果降低的最小。IA-32提供了一种被称作“Basic Flat Model”的分段模式可以达到这种效果。这种模式要求在GDT中至少要定义两个段描述符,一个用来引用Data Segment,另一个用来引用Code Segment。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论