当前位置: 首页 > news >正文

威海建设局网站楼盘信息公布锡林浩特建设局网站

威海建设局网站楼盘信息公布,锡林浩特建设局网站,注册公司那家网站做的比较好,wordpress外贸主题免费下载计算机已成为现代人日常工作、学习和生活中必不可少的工具。操作系统是计算机之魂#xff0c;作为用户使用计算机的接口#xff0c;它负责调度执行各个用户程序#xff0c;使计算机完成特定的任务#xff1b;作为计算机硬件资源的管理者#xff0c;它负责协调计算机中各类…计算机已成为现代人日常工作、学习和生活中必不可少的工具。操作系统是计算机之魂作为用户使用计算机的接口它负责调度执行各个用户程序使计算机完成特定的任务作为计算机硬件资源的管理者它负责协调计算机中各类设备高效地工作。操作系统的重要性不言而喻。 对于软件工程师理解操作系统的工作原理和关键机制是设计高质量应用程序的前提但要做到这一点是十分困难的。 一方面操作系统设计涉及计算机科学与工程学科的方方面面包括数据结构与算法、计算机组成与系统结构、计算机网络甚至程序设计语言与编译系统等核心知识以及并发、同步和通信等核心概念。 另一方面作为一个复杂庞大的软件产品理解操作系统更需要理论与实践深度结合。 操作系统的相关学习资料十分丰富。有阐述基本原理者有剖析典型系统者还有构造示例系统者有面向专业理论者亦有面向应用实践者。角度多种多样内容简繁不一。 ​本书的最大特点在于作者结合其多年的Linux操作系统实际教学经验编撰而成。作为一位经验丰富的高级软件工程师和专业教师本书作者基于自己学习和研究Linux的心得创新性地以一个mykernel和MenuOS为基础实验平台进行教学和实验组织实现了理论学习与工程实践的自然融合达到了事半功倍的效果。 同时书中设计了丰富的单元测试题和实验引导读者循序渐进地掌握所学知识并有效地促进读者深入思考和实践所学内容。 作者基于本书开设的操作系统课程其教学形式涉及面对面的课堂教学和在线慕课教学选课对象既包括软件工程硕士又包括一般工程实践者学习人数已数以万计。本书的出版体现了作者认真吸收大量的学员反馈不断优化课程的教学内容和过程组织的成果。 本文重点介绍计算机的工作原理具体涉及存储程序计算机工作模型、基本的汇编语言以及C语言程序汇编出来的汇编代码如何在存储程序计算机工作模型上一步步地执行。其中重点分析了函数调用堆栈相关汇编指令如call/ret和pushl/popl。 存储程序计算机工作模型 存储程序计算机的概念虽然简单但在计算机发展史上具有革命性的意义至今为止仍是计算机发展史上非常有意义的发明。一台硬件有限的计算机或智能手机能安装各种各样的软件执行各种各样的程序这在人们看起来都理所当然其实背后是存储程序计算机的功劳。 存储程序计算机的主要思想是将程序存放在计算机存储器中然后按存储器中的存储程序的首地址执行程序的第一条指令以后就按照该程序中编写好的指令执行直至程序执行结束。 相信很多人特别是学习计算机专业的人都听说过图灵机和冯·诺依曼机。图灵机关注计算的哲学定义是一种虚拟的抽象机器是对现代计算机的首次描述。只要提供合适的程序图灵机就可以做任何运算。基于图灵机建造的计算机都是在存储器中存储数据程序的逻辑都是嵌入在硬件中的。 与图灵机不同冯·诺依曼机是一个实际的体系结构我们称作冯·诺依曼体系结构它至今仍是几乎所有计算机平台的基础。我们都知道“庖丁解牛”这个成语比喻经过反复实践掌握了事物的客观规律做事得心应手运用自如。冯·诺依曼体系结构就是各种计算机体系结构需要遵从的一个“客观规律”了解它对于理解计算机和操作系统非常重要。下面我们就来看看什么是冯·诺依曼体系结构。 在19441945年期间冯·诺依曼指出程序和数据在逻辑上是相同的程序也可以存储在存储器中。冯·诺依曼体系结构的要点包括 冯·诺依曼体系结构如图1-1所示其中运算器、存储器、控制器、输入设备和输出设备5大基本类型部件组成了计算机硬件 图1-1 冯·诺依曼体系结构 计算机内部采用二进制来表示指令和数据 将编写好的程序和数据先存入存储器中然后启动计算机工作这就是存储程序的基本含义。 计算机硬件的基础是CPU它与内存和输入/输出I/O设备进行交互从输入设备接收数据向输出设备发送数据。 CPU由运算器算术逻辑单元ALU、控制器和一些寄存器组成。有一个非常重要的寄存器称为程序计数器在IA32x86-32中是EIP指示将要执行的下一条指令在存储器中的地址。 C/C程序员可以将EIP看作一个指针因为它总是指向某一条指令的地址。CPU就是从EIP指向的那个地址取过来一条指令执行执行完后EIP会自动加一执行下一条指令然后再取下一条指令执行CPU像“贪吃蛇”一样总是在内存里“吃”指令。 CPU、内存和I/O设备通过总线连接。内存中存放指令和数据。 “计算机内部采用二进制来表示指令和数据”表明指令和数据的功能和处理是不同的但都可以用二进制的方式存储在内存中。 上述第3个要点指出了冯·诺依曼体系结构的核心是存储程序计算机。 我们用程序员的思维来对存储程序计算机进行抽象如图1-2所示。 图1-2 存储程序计算机工作原理示意图 我们可以把CPU抽象成一个for循环因为它总是在执行next instruction下一条指令然后从内存里取下一条指令来执行。从这个角度来看内存保存指令和数据CPU负责解释和执行这些指令它们通过总线连接起来。这里揭示了计算机可以自动化执行程序的原理。 这里存在一个问题CPU能识别什么样的指令我们这里需要有一个定义。学过编程的读者基本都知道API也就是应用程序编程接口。 而对于程序员来讲还有一个称为ABI的接口它主要是一些指令的编码。在指令编码方面我们不会涉及那么具体的细节而只会涉及和汇编相关的内容。 至于这些指令是如何编码成二进制机器指令的我们不必关心有兴趣的读者可以查找指令编码的相关资料。此外这些指令会涉及一些寄存器这些寄存器有些约定我们约定什么样的指令该用什么寄存器。 同时我们也需要了解寄存器的布局。还有大多数指令可以直接访问内存对于x86-32计算机指令集来讲这也是一个重要的概念。 对于x86-32计算机有一个EIP寄存器指向内存的某一条指令EIP是自动加一的不是一个字节也不是32位而是加一条指令虽然x86-32中每条指令占的存储空间不一样但是它能智能地自动加到下一条指令它还可以被其他指令修改如call、ret、jmp等这些指令对应C语言中的函数调用、return和if else语句。 现在绝大多数具有计算功能的设备小到智能手机大到超级计算机基本的核心部分可以用冯·诺依曼体系结构存储程序计算机来描述。因此存储程序计算机是一个非常基本的概念是我们理解计算机系统工作原理的基础。 x86-32汇编基础 Intel处理器系列也称为x86经过不断的发展体系结构经历了16位、32位和64位几个关键阶段。32位的体系结构称为IA3264位体系结构称为x86-64但为了明确区分两者本书中把32位体系结构称作x86-32。本书与Linux内核采用的汇编格式保持一致采用ATT汇编格式。 1.x86-32 CPU的寄存器 为了便于读者理解下面先来介绍16位的8086 CPU的寄存器。8086 CPU中总共有14个16位的寄存器AX、BX、CX、DX、SP、BP、SI、DI、IP、FLAG、CS、DS、SS和ES。这14个寄存器分为通用寄存器、控制寄存器和段寄存器3种类型。 通用寄存器又分为数据寄存器、指针寄存器和变址寄存器。 AX、BX、CX和DX统称为数据寄存器。 qAXAccumulator累加寄存器也称为累加器。 qBXBase基地址寄存器。 qCXCount计数器寄存器。 qDXData数据寄存器。 SP和BP 统称为指针寄存器。 qSPStack Pointer堆栈指针寄存器。 qBPBase Pointer基指针寄存器。 SI和DI统称为变址寄存器。 qSISource Index源变址寄存器。 qDIDestination Index目的变址寄存器。 控制寄存器主要分为指令指针寄存器和标志寄存器。 qIPInstruction Pointer指令指针寄存器。 qFLAG标志寄存器。 段寄存器主要有代码段寄存器、数据段寄存器、堆栈段寄存器和附加段寄存器。 qCSCode Segment代码段寄存器。 qDSData Segment数据段寄存器。 qSSStack Segment堆栈段寄存器。 qESExtra Segment附加段寄存器。 以上数据寄存器AX、BX、CX和DX都可以当作两个单独的8位寄存器来使用如图1-3所示以AX寄存器为例。 图1-3 AX 寄存器示意图 qAX寄存器可以分为两个独立的8位的AH和AL寄存器。 qBX寄存器可以分为两个独立的8位的BH和BL寄存器。 qCX寄存器可以分为两个独立的8位的CH和CL寄存器。 qDX寄存器可以分为两个独立的8位的DH和DL寄存器。 除了上面4个数据寄存器以外其他寄存器均不可以分为两个独立的8位寄存器。注意每个分开的寄存器都有自己的名称可以独立存取。程序员可以利用数据寄存器的这种“可分可合”的特性灵活地处理字/字节的信息。 了解了16位的8086 CPU的寄存器之后我们再来看32位的寄存器。 IA32所含有的寄存器包括 q4个数据寄存器EAX、EBX、ECX和EDX。 q2个变址和指针寄存器ESI和EDI。 q2个指针寄存器ESP和EBP。 q6个段寄存器ES、CS、SS、DS、FS和GS。 q1个指令指针寄存器EIP。 q1个标志寄存器EFlags。 32位寄存器只是把对应的16位寄存器扩展到了32位如图1-4所示为EAX寄存器示意图它增加了一个E。所有开头为E的寄存器一般是32位的。 EAX累加寄存器、EBX基址寄存器、ECX计数寄存器和EDX数据寄存器都是通用寄存器程序员在写汇编码时可以自己定义如何使用它们。EBP是堆栈基址指针比较重要ESI、EDI是变址寄存器ESP也比较重要它是堆栈栈顶寄存器。 这里可能会涉及堆栈的概念学过数据结构课程的读者应该知道堆栈的概念本书后面会具体讲到push指令压栈和pop指令出栈它是向一个堆栈里面压一个数据和从堆栈里面弹出一个数据。这些都是32位的通用寄存器。 图1-4 EAX寄存器示意图 值得注意的是在16位CPU中AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址但在32位CPU中32位寄存器EAX、EBX、ECX和EDX不仅可以传送数据、暂存数据保存算术逻辑运算结果还可以作为指针寄存器因此这些32位寄存器更具通用性。 除了通用寄存器外还有一些段寄存器。虽然段寄存器在本书中用得比较少但还是要了解一下。除了CS、DS、ES和SS外还有其他附加段寄存器FS和GS。 常用的是CS寄存器和SS寄存器。我们的指令都存储在代码段在定位一个指令时使用CS:EIP来准确指明它的地址。 也就是说首先需要知道代码在哪一个代码段里然后需要知道指令在代码段内的相对偏移地址EIP一般用CS:EIP准确地标明一个指令的内存地址。还有堆栈段每一个进程都有自己的堆栈段在Linux系统里每个进程都有一个内核态堆栈和一个用户态堆栈。 标志寄存器的功能细节比较复杂烦琐本书就不仔细介绍了读者知道标志寄存器可以保存当前的一些状态就可以了。 现在主流的计算机大多都是采用64位的CPU那么我们也需要简单了解一下x86-64的寄存器。实际上64位和32位的寄存器差别也不大它只是从32位扩展到了64位。前面带个“R”的都是指64位寄存器如RAX、RBX、RCX、RDX、RBP、RSI、RSP还有Flags改为了RFLAGSEIP改为了RIP。 另外还增加了更多的通用寄存器如R8、R9等这些增加的通用寄存器和其他通用寄存器只是名称不一样在使用中都是遵循调用者使用规则简单说就是随便用。 2.数据格式 在Intel的术语规范中字表示16位数据类型在IA32中32位数称为双字在x86-64中64位数称为四字。图1-5所示为C语言中基本类型的IA32表示其中列出的汇编代码后缀在汇编代码中会经常看到。 图1-5 C语言中基本类型的IA32表示 3.寻址方式和常用汇编指令 汇编指令包含操作码和操作数其中操作数分为以下3种 1立即数即常数如$8用$开头后面跟一个数值 2寄存器数表示某个寄存器中保存的值如%eax而对字节操作而言是8个单字节寄存器中的一个如%alEAX寄存器中的低8位 3存储器引用根据计算出的有效地址来访问存储器的某个位置。 还有一些常见的汇编指令我们来看它们是如何工作的。最常见的汇编指令是mov指令movl中的l是指32位movb中的b是指8位movw中的w是指16位movq中的q是指64位。我们以32位为主进行介绍。 首先介绍寄存器寻址。所谓寄存器寻址就是操作的是寄存器不和内存打交道如%eax其中%开头后面跟一个寄存器名称。 movl %eax%edx 上述代码把寄存器%eax的内容放到%edx中。如果把寄存器名当作C语言代码中的变量名它就相当于 edx eax; 立即寻址immediate是用一个$开头后面跟一个数值。例如 movl $0x123 %edx 就是把0x123这个十六进制的数值直接放到EDX寄存器中。如果把寄存器名当作C语言代码中的变量名它就相当于 edx 0x123; 立即寻址也和内存没有关系。 直接寻址direct是直接用一个数值开头没有$符号。开头有$符号的数值表示这是一个立即数没有$符号表示这是一个地址。例如 movl 0x123 %edx 就是把十六进制的0x123内存地址所指向的那块内存里存储的数据放到EDX寄存器里这相当于C语言代码 edx *(int*)0x123; 把0x123这个数值强制转化为一个32位的int型变量的指针再用一个*取它指向的值然后放到EDX寄存器中这就称为直接寻址。 换句话说就是用内存地址直接访问内存中的数据。 间接寻址就是寄存器加个小括号。举例说明%ebx这个寄存器中存的值是一个内存地址加个小括号表示这个内存地址所存储的数据我们把它放到EDX寄存器中 move (%ebx), %edx 就相当于 edx *(int*)ebx; 把这个EBX寄存器中存储的数值强制转化为一个32位的int型变量的指针再用一个*取它指向的值然后放到EDX寄存器中这称为间接寻址。 变址寻址比间接寻址稍微复杂一点。例如 movl 4(%ebx), %edx 读者会发现代码中“%ebx”前面出现了一个4也就是在间接寻址的基础上在原地址上加上一个立即数4相当于 edx *(int*)(ebx4) 把这个EBX寄存器存储的数值加4然后强制转化为一个32位的int类型的指针再用一个*取它指向的值然后放到EDX寄存器中这称为变址寻址。 如上所述的CPU对寄存器和内存的操作方法都是比较基础的知识需要牢固掌握。 x86-32中的大多数指令都能直接访问内存但还有一些指令能直接对内存操作如push/pop。它们根据ESP寄存器指向的内存位置进行压栈和出栈操作注意这是指令执行过程中默认使用了特定的寄存器。 还需要特别说明的是本书中使用的是ATT汇编格式这也是Linux内核使用的汇编格式与Intel汇编格式略有不同。 我们在搜索资料时可能会遇到Intel汇编代码一般来说全是大写字母的一般是Intel汇编全是小写字母的一般是ATT汇编。 本书中的代码用到的寄存器名称都遵守ATT汇编格式采用全小写的方式而正文中需要使用寄存器名称一般使用大写因为它们是首字母缩写。 还有几个重要的指令pushl/popl和call/ret。pushl表示32位的push如 pushl %eax 就是把EAX寄存器的值压到堆栈栈顶。它实际上做了这样两个动作其中第一个动作为 subl $4 %esp 把堆栈的栈顶ESP寄存器的值减4。因为堆栈是向下增长的所以用减指令subl也就是在栈顶预留出一个存储单元。第二个动作为 movl %eax (%esp) 把ESP寄存器加一个小括号间接寻址就是把EAX寄存器的值放到ESP寄存器所指向的地方这时ESP寄存器已经指向预留出的存储单元了。 接下来介绍popl指令如 popl %eax 就是从堆栈的栈顶取一个存储单元32位数值从堆栈栈顶的位置放到EAX寄存器里这称为出栈。出栈同样对应两个操作 movl (%esp), %eax addl $4, %esp 第一步是把栈顶的数值放到EAX寄存器里然后用指令addl把栈顶加4相当于栈向上回退了一个存储单元的位置也就是栈在收缩。每次执行指令pushl栈都在增长执行指令popl栈都在收缩。 call指令是函数调用调用一个地址。例如 call 0x12345 上述代码实际上做了两个动作如下两条伪指令注意这两个动作并不存在实际对应的指令我们用“*”来特别标记一下这两个动作是由硬件一次性完成的。出于安全方面的原因EIP寄存器不能被直接使用和修改。 pushl %eip (*) movl $0x12345, %eip (*) 上述伪指令先是把当前的EIP寄存器压栈把0x12345这个立即数放到EIP寄存器里该寄存器是用来告诉CPU下一条指令的存储地址的。 把当前的EIP寄存器的值压栈就是把下一条指令的地址保存起来然后给EIP寄存器又赋了一个新值0x12345也就是CPU执行的下一条指令就是从0x12345位置取得的。 再看与call指令对应的指令retret指令是函数返回例如 ret 上述代码实际上做了一个动作如下一条伪指令注意这个动作并不存在实际对应的指令我们用“*”来特别标记一下这个动作是由硬件一次性完成的。出于安全方面的原因EIP寄存器不能被直接使用和修改。 popl %eip(*) 也就是把当前堆栈栈顶的一个存储单元一般是由call指令压栈的内容放到EIP寄存器里。上述pushl/popl和call/ret汇编指令对应执行的动作汇总如图1-6所示。 图1-6 pushl/popl和call/ret汇编指令 总结一下call指令对应了C语言里我们调用一个函数也就是call一个函数的起始地址。ret指令是把调用函数时压栈的EIP寄存器的值即call指令的下一条指令的地址还原到EIP寄存器里ret指令之后的下一条指令也就回到函数调用位置的下一条指令。 换句话说就是函数调用结束了继续执行函数调用之后的下一条指令这和C语言中的函数调用过程是严格对应的。但是需要注意的是带个“*”的指令表示这些指令都是不能被程序员直接使用的是伪指令。 因为EIP寄存器不能被程序员直接修改只能通过专用指令如call、ret和jmp等间接修改。 若程序员可以直接修改EIP寄存器那么会有严重的安全隐患。读者可以思考一下为什么我们就不展开讨论了。 4.汇编代码范例解析 我们已经对指令和寄存器有了大致的了解下面做一个练习来验证我们的理解。在堆栈为空栈的情况下执行如下汇编代码片段之后堆栈和寄存器都发生了哪些变化 1 push $8 2 movl %esp, %ebp 3 subl $4, %esp 4 movl $8, (%esp) 我们分析这段汇编代码每一步都做了什么动作。首先在堆栈为空栈的情况下EBP和ESP寄存器都指向栈底。 第1行语句是将立即数8压栈即先把ESP寄存器的值减4然后把立即数8放入当前堆栈栈顶位置。 第2行语句是把ESP寄存器的值放到EBP寄存器里就是把ESP寄存器存储的内容放到EBP寄存器中把EBP寄存器也指向当前ESP寄存器所指向的位置。 换句话说在堆栈中又新建了一个逻辑上的空栈这一点理解起来并不容易读者暂时理解不了也没有关系。本书后面会将C语言程序汇编成汇编代码来分析函数调用是如何实现的其中会涉及函数调用堆栈框架。 第3行语句中的指令是subl是把ESP寄存器存储的数值减4也就是说栈顶指针ESP寄存器向下移了一个存储单元4个字节。 最后一行语句是把立即数8放到ESP寄存器所指向的内存地址也就是把立即数8通过间接寻址放到堆栈栈顶。 本例是关于栈和寄存器的一些操作的我们可以对照上述文字说明一步一步跟踪堆栈和寄存器的变化过程以便更加准确地理解指令的作用。 再来看一段汇编代码同样在堆栈为空栈的情况下执行如下汇编代码片段之后堆栈和寄存器都发生了哪些变化 1 pushl $8 2 movl %esp, %ebp 3 pushl $8 同样我们也分析一下这段汇编代码每一步都做了什么动作。首先在堆栈为空栈的情况下EBP和ESP寄存器都指向栈底。 第1行语句是将立即数8压栈即堆栈多了一个存储单元并存了一个立即数8同时也改变了ESP寄存器。 第2行语句把ESP寄存器的值放到EBP寄存器里堆栈空间没有变化但EBP寄存器发生了变化。 第3行语句将立即数8压栈即堆栈多了一个存储单元并存了一个立即数8。 读者会发现这个例子和上一个例子的实际效果是完全一样的。 小试牛刀之后再看下面这段更加复杂一点的汇编代码 1 pushl $8 2 movl %esp, %ebp 3 pushl %esp 4 pushl $8 5 addl $4, %esp 6 popl %esp 这段汇编代码同样首先在堆栈为空栈的情况下EBP和ESP寄存器都指向栈底。 第1行语句是将立即数8压栈即堆栈多了一个存储单元并保存立即数8同时也改变了ESP寄存器。 第2行语句是把ESP寄存器的值放到EBP寄存器里堆栈空间没有变化但EBP寄存器发生了变化。 第3行语句是把ESP寄存器的内容压栈到堆栈栈顶的存储单元里。需要注意的是pushl指令本身会改变ESP寄存器。“pushl %esp”语句相当于如下两条指令 subl $4, %esp movl %esp, (%esp) 显然在保存ESP寄存器的值到堆栈中之前改变了ESP寄存器保存到栈顶的数据应该是当前ESP寄存器的值减4。ESP寄存器的值发生了变化同时栈空间多了一个存储单元保存变化后的ESP寄存器的值。 第4行语句是将立即数8压栈即堆栈多了一个存储单元保存立即数8同时也改变了ESP寄存器。 第5行语句是把ESP寄存器的值加4这相当于堆栈空间收缩了一个存储单元。 最后一条语句相当于如下两条指令 movl (%esp), %esp addl $4, %esp 也就是把当前栈顶的数据放到ESP寄存器中然后又将ESP寄存器加4。这一段代码比较复杂因为ESP寄存器既作为操作数又被pushl/popl指令在执行过程中使用和修改。 读者需要仔细分析和思考这段汇编代码以理解整个执行过程本书后续内容会结合C代码的函数调用和函数返回来进一步理解这段汇编代码中涉及的建立一个函数调用堆栈和拆除一个函数调用堆栈。 《庖丁解牛Linux内核分析》 孟宁 娄嘉鹏 刘宇栋 著 本书从理解计算机硬件的核心工作机制存储程序计算机和函数调用堆栈和用户态程序如何通过系统调用陷入内核中断异常入手通过上下两个方向双向夹击的策略并利用实际可运行程序的反汇编代码从实践的角度理解操作系统内核然后开始分析Linux内核源代码从系统调用陷入内核进程调度与进程切换最后返回到用户态进程。
http://www.pierceye.com/news/763003/

相关文章:

  • ai网站制作的图片
  • 自己想开个网站怎么弄移动端网站设计欣赏
  • 国外网站建站上海品牌策划设计
  • 郑州网站制作选择乐云seo网站建设误区图
  • 湖南智能网站建设多少钱会声会影免费模板网站
  • 社区网站建设方案书建站之星官方网站
  • 过时的网站什么公司做企业网站
  • 最新企业网站搜索引擎优化是做什么
  • 提高网站公信力 单仁手机设计培训网站建设
  • asp.net网站管理系统域名注册报备
  • 买了个网站后怎么做如何提高 网站的点击量
  • 哪些行业网站推广做的多o2o商城源码
  • 北京seo站内优化电商网站前端页面响应式设计
  • 贵港seo关键词整站优化网站恶意攻击
  • 王磊网络网站建设公关
  • 怎么建网站做推广win网站建设
  • 在线做英语题的网站wordpress被设置不录入
  • 桃花岛网站是什么翻硬币网站怎么做
  • 做海报的网站有哪些内容windows同步wordpress
  • 制作网页的网站费用属于资本性支出吗安徽区块链虚拟币网站开发方案
  • 做网站前产品经理要了解什么搜索引擎优化免费
  • 广州网站建设技术方案营销网站推广策略
  • 郑州网站建设、中国菲律宾铁路项目
  • 潜江网站开发学校网站建设领导小组
  • 桂林临桂区建设局网站厦门 微网站建设公司哪家好
  • 如何用云服务器搭建个人网站有些人做网站不用钱的,对吗?
  • 月嫂网站建设方案建设网站询价对比表模板
  • 医院网站建设 价格低深圳市高端网站建设
  • 太原做学校网站的公司网站免费观看
  • 企业网络营销是什么seo教程百度云