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

南宁定制网站建设企业seo如何优化

南宁定制网站建设,企业seo如何优化,自助建设分销商城网站,休闲旅游产品营销网站的建设策略内核文件kernel.bin是elf格式的二进制可执行文件#xff0c;初始化内核就是根据elf规范将内核文件中的段#xff08;segment#xff09;展开到#xff08;复制到#xff09;内存中的相应位置。在分页模式下#xff0c;程序是靠虚拟地址来运行的#xff0c;无论是内核还是…内核文件kernel.bin是elf格式的二进制可执行文件初始化内核就是根据elf规范将内核文件中的段segment展开到复制到内存中的相应位置。在分页模式下程序是靠虚拟地址来运行的无论是内核还是用户程序它们对cpu来说都是指令或数据、没什么区别交给cpu的指令或数据的地址一律被认为是虚拟地址。坦白说内核文件中的地址是在编译阶段确定的里面都是虚拟地址程序也是靠这些虚拟地址来运行。但这些虚拟地址实际上是我们在初始化内核阶段规划好的即想安排内核在哪片虚拟内存中就将内核地址编译成对应的虚拟地址。而目前我们初始化的是内核它在物理低端1MB内存中初始化工作取决于这1MB物理内存中哪块空间可用所以现在还要看前面的内存分布图从中找块合适的内存空间来容纳内核映像。 其实大家早已经知道内核的入口虚拟地址是0xc0001500啦。但现在大家要假装不知道^_^配合一下啊咱们说一下0xc0001500是怎么来的。 物理内存中0x900处是loader.bin加载的地址在loader.bin的开始部分是GDT它可是必须要保留下来的可不能覆盖我们不打算在内核中重新定义它以后都要指望它了。正如伟大领袖虽然仙逝了但威望犹在虽然loader的工作结束啦但loader所完成的工作成果咱们还得继续发扬继续用。预计loader.bin的大小不会超过2000字节。所以咱们可选的起始物理地址是0x90020000x10d0不要把注意力放在这个奇怪的数上偶然得出的。内存很大但也尽量往低了选于是凑了个整数选了0x1500做为内核映像的入口地址。 根据咱们的页表低端1MB的虚拟内存与物理内存是一一对应的所以物理地址是0x1500对应的虚拟地址是0xc0001500。这就解释了在5.3.1节中链接命令ld中用-Ttext指定了代码段的起始虚拟地址再把命令搬过来给大家看下 ld kernel/main.o -Ttext 0xc0001500 -e main -o kernel/kernel.bin 好现在咱们得说一下初始化内核的代码见代码: 193 ;---------- 将kernel.bin中的segment拷贝到编译的地址 ----------- 194 kernel_init: 195 xor eax, eax 196 xor ebx, ebx ;ebx记录程序头表地址 197 xor ecx, ecx ;cx记录程序头表中的program header数量 198 xor edx, edx ;dx 记录program header尺寸,即e_phentsize 199 200 mov dx, [KERNEL_BIN_BASE_ADDR 42] ; 偏移文件42字节处的属性是e_phentsize,表示program header大小 201 mov ebx, [KERNEL_BIN_BASE_ADDR 28] ; 偏移文件开始部分28字节的地方是e_phoff, 表示第1 个program header在文件中的偏移量 202 ; 其实该值是0x34,不过还是谨慎一点这里来读取实际值 203 add ebx, KERNEL_BIN_BASE_ADDR 204 mov cx, [KERNEL_BIN_BASE_ADDR 44] ; 偏移文件开始部分44字节的地方是e_phnum,表示有几个program header 205 .each_segment: 206 cmp byte [ebx 0], PT_NULL ; 若p_type等于 PT_NULL,说明此program header未使用。 207 je .PTNULL 208 209 ;为函数memcpy压入参数,参数是从右往左依然压入.;函数原型类似于 memcpy(dst,src,size) 210 push dword [ebx 16] ; program header中偏移16字节的地方是p_filesz, ;压入函数memcpy的第三个参数:size 211 mov eax, [ebx 4] ; 距程序头偏移量为4字节的位置是p_offset 212 add eax, KERNEL_BIN_BASE_ADDR ; 加上kernel.bin被加载到的物理地址,eax为该段的物理地址 213 push eax ; 压入函数memcpy的第二个参数:源地址 214 push dword [ebx 8] ; 压入函数memcpy的第一个参数:目的地址;偏移程序头8字节的位置是p_vaddr这就是目的地址 215 call mem_cpy ; 调用mem_cpy完成段复制 216 add esp,12 ; 清理栈中压入的三个参数 217 .PTNULL: 218 add ebx, edx ; edx为program header大小,即e_phentsize,;在此ebx指向下一个program header 219 loop .each_segment 220 ret 221 222 ;---------- 逐字节拷贝 mem_cpy(dst,src,size) ------------ 223 ;输入:栈中三个参数(dst,src,size) 224 ;输出:无 225 ;--------------------------------------------------------- 226 mem_cpy: 227 cld 228 push ebp 229 mov ebp, esp 230 push ecx ; rep指令用到了ecx; 但ecx对于外层段的循环还有用故先入栈备份 231 mov edi, [ebp 8] ; dst 232 mov esi, [ebp 12] ; src 233 mov ecx, [ebp 16] ; size 234 rep movsb ; 逐字节拷贝 235 236 ;恢复环境 237 pop ecx 238 pop ebp 239 ret对于可执行程序我们只对其中的段segment感兴趣它们才是程序运行的实质指令和数据的所在地所以我们要找出程序中所有的段。 函数kernel_init的作用是将kernel.bin中的段segment拷贝到各段自己被编译的虚拟地址处将这些段单独提取到内存中这就是平时所说的内存中的程序映像。kernel_init的原理是分析程序中的每个段segment如果段类型不是PT_NULL空程序类型就将该段拷贝到编译的地址中。 现在内核已经被加载到KERNEL_BIN_BASE_ADDR地址处该处是文件头elf_header。在我们的程序中遍历段的方式是指向第一个程序头后每次增加一个段头的大小即e_phentsize。该属性位于偏移程序开头42字节处。为了以后遍历段时方便避免了频繁的访问内存在第200行我们用寄存器dx来存储段头大小这样每遍历一个段头时就直接从dx中获取段头大小这将在第218行体现。 为了找到程序中所有的段必须要获取程序头表。在文件开头偏移28字节处是属性e_phoff该属性表示程序头表在文件中的偏移量程序头表是程序头program header的数组所以e_phoff也就是第1 个program header在文件中的偏移量。第201行在内存e_phoff处取值将得到的程序头表偏移量存入寄存器ebx。 我们需要的是程序头表的物理地址由于此时的ebx还是程序头表文件内的偏移量所以要将其加上内核的加载地址这样才是程序头表的物理地址。所以在第203行为ebx加上了内核文件的加载地址KERNEL_BIN_BASE_ADDR。最终ebx寄存器做为程序头表的基址用它来遍历每一个段此时ebx指向程序中的第1 个program header。 我们已经知道段是由程序头program header来描述的一个程序头代表一个段。在知道了第一个程序头的地址后为了遍历所有的程序头还需要知道程序中程序头的数量也就是段的数量这是由elf_header中的属性e_phnum决定它在elf_header中偏移为44。我们通常用cx寄存器来做循环计数器所以在第204行汇编语句“mov cx, [KERNEL_BIN_BASE_ADDR 44]”将段的数量赋值给寄存器cx。 现在程序头表地址在寄存器ebx中而且又知道了程序头表中段的数量所以现在可以遍历每一个段的信息啦其工作在代码第205~220行中完成。 在第206行程序先判断下段的类型是不是PT_NULLPT_NULL是在boot/include/boot.inc中定义的宏其值为0该意义表示空段类型。PT_NULL也可以在linux系统的/usr/include/elf.h中找到其定义#define PT_NULL 0 在207行如果发现该段是空段类型的话就跨过该段不处理跳到.PTNULL处也就是第217行。 指定下一个段是通过在程序头表地址处加上一个段的大小e_phentsize来实现的e_phentsize的值咱们已经将其存储在dx寄存器啦所以在第218行直接将ebx也就是当前program header地址加上edxebx便指向了下一个段的program header。edx的高16位为0所以这里用add ebx, edx没有问题。 第209~216行程序中的段通过mem_cpy函数复制到段自身的虚拟地址处。在这里我们涉及到了函数调用约定的知识不过为了叙述的更清楚在这里我不想简单地说在下一章中我们专门拿出一节来说这事儿。在此我还是本着够用的原则把用到的部分给您说明白。 我们在此实现的函数是mem_cpy不是c标准库中的memcpy函数将来我们会在内核中实现memcpy。memcpy原型是void *memcpy(void *dest, const void *src, size_t n)功能是将src指向的地址空间处的连续n个字节拷贝到dest指向的地址空间。我们的学习它的用法在汇编语言中用mem_cpy函数实现了它此函数的原型相当于mem_cpy(void* dst, void* src, int size)。所以我们也要提供三个参数才能使用它。这三个参数都在程序头program header中所以它们都可以基于ebx再增加适当的偏移量来得到。program header结构很容易理解210~214行的代码。 第215行是调用 mem_cpy这涉及到为该函数传入参数的问题。在汇编语言中传递参数的方法太多了原因是汇编语言太灵活了不怎么受约束咱们可以访问到的资源太多了。所以主调函数可以把参数放在寄存器中也可以放在栈中而栈就是内存所以只要大家高兴也可以把参数直接放到某块内存中类似共享内存的方式来传递参数。主调函数以上面任意一种方式传递参数被调函数都可以轻松地拿到参数。
http://www.huolong8.cn/news/340107/

相关文章:

  • 阿里云网站注册安宁网站建设熊掌号
  • 网页设计网站开发需要什么软件上海网站建设报价
  • 有哪些ui的设计网站wordpress虚拟资源下载博客
  • 竞价网站建设做建材一般去什么网站宣传
  • 建网站商城平台wordpress字体在哪个文件夹
  • 人工智能设计网站外贸公司网站模板免费
  • 哪些行业网站推广做的多建设银行网银盾不能打开网站
  • wordpress服务器系统seo推广优化排名软件
  • 网站预算表怎么做上海网站设计专业团队
  • 网站横向菜单做精神科网站价格
  • 如何做地图的ppt模板下载网站wordpress 自定义结构
  • 怎么样做网站才能适应手机屏幕用html做的网站加背景音乐
  • 上海网站建设广告语三星网上商城优惠码
  • 工商局注册公司网站设计制作个人网站
  • 长沙毕业设计代做网站价格合肥seo整站优化网站
  • 南通精诚建设集团有限公司网站做图片素材的网站
  • 宿迁网站制作公司三亚最新通告文昌最新通告
  • 网站建设资金的请示泉州网站建设报价
  • 网站开发题目女生做网站编辑怎么样
  • 做室内3d设计的网站旅游网站建设的现状
  • 云南网站建设及优化南昌招网页设计师的公司
  • 电子商务网站开发实训总结godaddy
  • 无锡新吴区住房建设和交通局网站wordpress 运行速度慢
  • 制作网站房子竣工验收在哪个网站查
  • 云浮市住房和城乡建设局网站wordpress如何修改后台登录地址
  • 网站的页面大小包装盒网站模板下载
  • 手机品牌网站网站模板分享
  • 建设学校网站的意义搜索引擎官网
  • 百度的网站关键词被篡改赣州九一人才网最新招聘
  • 做外包网站的公司是怎样的哔哩哔哩网站建设模板