【Linux0.11 源码历险记 3】《开启分页》

2023-05-16

下面我们就正式进入head.s 的代码:

.text
.globl _idt,_gdt,_pg_dir,_tmp_floppy_area
_pg_dir:
startup_32:
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	mov %ax,%gs
	lss _stack_start,%esp

这里是将所用的*s寄存器都置为0x10其实就是选择了gdt里的第二个表项。
lss 指令的作用,就是让ss:esp 这个栈顶指针指向了 _stack_start 这个标号的位置。

下面又设置idt和gdt:

	call setup_idt
	call setup_gdt
	
	......
	
setup_idt:
	lea ignore_int,%edx
	movl $0x00080000,%eax
	movw %dx,%ax		/* selector = 0x0008 = cs */
	movw $0x8E00,%dx	/* interrupt gate - dpl=0, present */

	lea _idt,%edi
	mov $256,%ecx
rp_sidt:
	movl %eax,(%edi)
	movl %edx,4(%edi)
	addl $8,%edi
	dec %ecx
	jne rp_sidt
	lidt idt_descr
	ret
//循环256次,让所有的中断向量指向ignore_int
/*
 *  setup_gdt
 *
 *  This routines sets up a new gdt and loads it.
 *  Only two entries are currently built, the same
 *  ones that were built in init.s. The routine
 *  is VERY complicated at two whole lines, so this
 *  rather long comment is certainly needed :-).
 *  This routine will beoverwritten by the page tables.
 */
setup_gdt:
	lgdt gdt_descr
	ret
	
......
	
ignore_int:
	......
	
idt_descr:
	.word 256*8-1		# idt contains 256 entries
	.long _idt

其中gdt:

_gdt:	
	.quad 0x0000000000000000	/* NULL descriptor */
	.quad 0x00c09a0000000fff	/* 16Mb */
	.quad 0x00c0920000000fff	/* 16Mb */
	.quad 0x0000000000000000	/* TEMPORARY - don't use */
	.fill 252,8,0			/* space for LDT's and TSS's etc */

其中总体就是让gdt和idt进行重新指向:
在这里插入图片描述
下面就开始分页设置:

after_page_tables:
	pushl $0		# These are the parameters to main :-)
	pushl $0
	pushl $0
	pushl $L6		# return address for main, if it decides to.
	pushl $_main
	jmp setup_paging
L6:
	jmp L6			# main should never return here, but
				# just in case, we know what happens.

其中setup_paging 如下:

setup_paging:
	movl $1024*5,%ecx		/* 5 pages - pg_dir+4 page tables */
	xorl %eax,%eax
	xorl %edi,%edi			/* pg_dir is at 0x000 */
	cld;rep;stosl
	movl $pg0+7,_pg_dir		/* set present bit/user r/w */
	movl $pg1+7,_pg_dir+4		/*  --------- " " --------- */
	movl $pg2+7,_pg_dir+8		/*  --------- " " --------- */
	movl $pg3+7,_pg_dir+12		/*  --------- " " --------- */
	movl $pg3+4092,%edi
	movl $0xfff007,%eax		/*  16Mb - 4096 + 7 (r/w user,p) */
	std
1:	stosl			/* fill pages backwards - more efficient :-) */
	subl $0x1000,%eax
	jge 1b
	xorl %eax,%eax		/* pg_dir is at 0x0000 */
	movl %eax,%cr3		/* cr3 - page directory start */
	movl %cr0,%eax
	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */
	ret			/* this also flushes prefetch-queue */

当时 linux-0.11 认为,总共可以使用的内存不会超过 16M,也即最大地址空间为 0xFFFFFF。

而按照当前的页目录表和页表这种机制,1 个页目录表最多包含 1024 个页目录项(也就是 1024 个页表),1 个页表最多包含 1024 个页表项(也就是 1024 个页),1 页为 4KB(因为有 12 位偏移地址),因此,16M 的地址空间可以用 1 个页目录表 + 4 个页表搞定。

因此在head开头后后面,有五个页表:

.org 0x1000 pg0:
.org 0x2000 pg1:
.org 0x3000 pg2:
.org 0x4000 pg3:
.org 0x5000

然后在页表目录里设置每一个页表对应的页表项:

setup_paging:
	movl $1024*5,%ecx		/* 5 pages - pg_dir+4 page tables */
	xorl %eax,%eax
	xorl %edi,%edi			/* pg_dir is at 0x000 */
	cld;rep;stosl
	movl $pg0+7,_pg_dir		/* set present bit/user r/w */
	movl $pg1+7,_pg_dir+4		/*  --------- " " --------- */
	movl $pg2+7,_pg_dir+8		/*  --------- " " --------- */
	movl $pg3+7,_pg_dir+12		/*  --------- " " --------- */
	movl $pg3+4092,%edi
	movl $0xfff007,%eax		/*  16Mb - 4096 + 7 (r/w user,p) */
	std
1:	stosl			/* fill pages backwards - more efficient :-) */
	subl $0x1000,%eax
	jge 1b
	xorl %eax,%eax		/* pg_dir is at 0x0000 */
	movl %eax,%cr3		/* cr3 - page directory start */
	movl %cr0,%eax
	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */
	ret			/* this also flushes prefetch-queue */

这样就把一开始的_pg_dir 位置给覆盖掉了。变成了页表的存储目录。同时做了映射,页表中的每一项都进行了填充,16MB虚拟地址跟前16MB物理地址一一对应起来了。

下面就可以进入c语言写的main函数了:

after_page_tables:
    push 0
    push 0
    push 0
    push L6
    push _main
    jmp setup_paging
...
setup_paging:
    ...
    ret

push把main函数的入口地址压入栈之后,set_paging一旦ret,那么就可以跳转到main函数的地址进行执行。同时栈内也有参数,这就是main函数传参和进入的方法。call 和 ret不需要配对使用,所以将main入栈之后,调用ret弹出,就可以去到main函数执行。
下面我们就要进入c的main函数了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Linux0.11 源码历险记 3】《开启分页》 的相关文章

  • JVM虚拟机栈

    虚拟机栈 每个线程在创建时都会创建一个虚拟机栈 xff0c 其内部保存一个个栈帧 xff0c 对应一次次java方法的调用 xff08 线程私有 xff09 生命周期与线程一致 作用 xff1a 主管java线程的运行 xff0c 保存局部
  • C++之串口通讯

    C 43 43 串口操作 简介代码头文件源码文件 示例创建两个虚拟串口用串口调试助手连接COM2来接数据编写测试代码发送数据结果 总结 简介 串行接口简称串口 xff0c 也称串行通信接口或串行通讯接口 xff08 通常指COM接口 xff
  • 用keil写程序时出现“C(162): error C249: 'DATA': SEGMENT TOO LARGE“的错误

    如果定义的数组不用更改就用 uchar code XX 10 61 根据数据的用处 xff0c 可以有以下几种选择 xff1a data xff1a 直接寻址 的片内RAM区低128B xff08 00H 7FH xff09 bdata x
  • ROS 与 Box Turtle、C Turtle、Indigo Igloo 、Jade Turtle 、Kinetic Kame 、Melodic Morenia、Noetic Ninjemys关系

    如果没有错的话相当于这个些都是ros的版本 xff0c 就是不同时期叫的名字不一样 xff0c 用于区别不同的版本 因为也是初学者 xff0c 都还没入门 xff0c 也是网上找的资料 xff0c 并根据自己的理解写的 xff0c 如果有错
  • C语言——VS编译器下程序运行结果闪退解决方法

    C语言 VS编译器下程序运行结果闪退解决方法 学习C语言的过程中可能会遇到这样的问题 xff0c 程序调试的时候没有错误 xff0c 可是在运行结果的时候会发现程序结果闪退 xff0c 导致看不到结果 在此 xff0c 本文总结对比了几种有
  • Gazebo 加载xacro文件和URDF文件的方式

    版权声明 xff1a lt 本博客所有内容均为自己在学习工作中的总结 摘录等 转载请注明出处 如有侵权请联系删除 gt https blog csdn net xuehuafeiwu123 article details 71108959
  • Gazebo显示加载xacro模型文件---改变模型的颜色注意事项

    在xacro文件中 xff0c 有下列语句是修改模型颜色的 xff1a 例 xff1a lt link name 61 34 base link 34 gt lt visual gt lt geometry gt lt box size 6
  • Gazebo中sdf文件和urdf和xacro文件的区别

    sdf文件 urdf文件和xacro文件都是模型文件 xacro文件是urdf文件的改进版 xff0c urdf文件只能在rviz等中显示 xff0c 不能在仿真器中显示出来 xacro文件可以在gazebo仿真器中显示出来 xff0c 相
  • Gazebo的xacro文件添加各种plugins

    官网地址 xff1a http gazebosim org tutorials tut 61 ros gzplugins Tutorial Using Gazebo plugins with ROS Gazebo plugins give
  • ROS中spawn_model方式加载xacro文件,设置模型的位置(xyz,rpy)

    例如加载turtlebot机器人launch文件如下 xff1a 在gazebo仿真中最后都是通过这种方式加载xacro文件的 lt launch gt lt arg name 61 34 base 34 gt lt arg name 61
  • BT1120

    BT1120是高清晰度电视 HDTV 演播室信号数字接口 图像数据是怎么用二进制数据组织在一起的呢 xff1f 个人理解 xff1a 在BT1120标准中说明的图像数据指的是图像的有效尺寸的数据 因为我们看到编码信号包括图像数据和图像基准码
  • 2021-10-22 常用的串口通讯协议

    串口通讯是什么 学术解释是 xff0c 通过总线在一个时间点连续发送一位数据的方法 如同弓箭手频繁射出弓箭一般 xff0c 嗖 嗖 嗖 串口通讯协议是什么 说的大白话一点 xff0c 就是串口通信时所使用的协议传输方式 串口通讯协议有几种呢
  • curl 命令详解

    curl 是一种命令行工具 xff0c 作用是发出网络请求 xff0c 然后获取数据 xff0c 显示在 34 标准输出 34 xff08 stdout xff09 上面 它支持多种协议 xff0c 下面列举其常用功能 一 查看网页源码 直
  • RS485/云台控制(PTZ)学习文档

    RS485 云台控制 xff08 PTZ xff09 学习文档 zxf 一 项目任务 xff1a 在linux环境下通过RS485串口实现对云台镜头的各种控制 xff08 包括摄像头的打开 xff0c 关闭 xff0c 各个方向的运动及运动
  • 为何某些公司不允许使用C++STL

    点击蓝字 关注我们 最初开始禁用 C 43 43 STL xff0c 是因为早期项目编码实践中留下的惯例 xff0c 被后来的程序员继承下来 老项目中这种选择尤其地多 不过如果有人将其上升到公司行为在不同项目中全面禁用 STL xff0c
  • C++vector用法总结

    点击蓝字 关注我们 来源自网络 xff0c 侵删 一 vector 1 vector 说明 1 xff09 vector是C 43 43 标准模板库中的部分内容 xff0c 它是一个多功能的 xff0c 能够操作多种数据结构和算法的模板类和
  • halcon中的Pose

    Pose 姿态描述的是一个刚性的3D转换 xff0c 即 xff0c 一种由任意平移和旋转组成的变换 在Halcon中 xff0c 一个pose是具有7个参数的元组 xff1a 3个参数描述平移 xff08 TransX TransY Tr
  • halcon中阈值分割算子用法

    1 threshold Image Region MinGray MaxGray xff1a 通过给定的阈值区间对图像进行分割 效果图 xff1a read image Audi2 39 audi2 39 fill interlace Au
  • HALCON guided_filter导向滤波算子分析

    1 guided filter Image ImageGuide ImageGuided Radius Amplitude 可应用在图像增强 xff0c HDR压缩 图像抠图及图像去雾等场景 参数 xff1a Radius xff1a 滤光
  • halcon edges_image算子分析

    edges image Image ImaAmp ImaDir Filter Alpha NMS Low High xff1a 使用Deriche Lanser Shen或者Canny 滤波器进行边缘提取 参数 xff1a Image xf

随机推荐

  • C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用

    NModbus的主站开发 1 开发环境要求 xff1a PC端作为主站 xff0c 控制器作为从站 2 PC端初始化代码 xff1a serialPort 61 new SerialPort serialPort PortName 61 3
  • OpenCVSharp Mat.Set<T>修改像素颜色

    笔记 xff1a Mat Set lt T gt 方法修改图像中的颜色 xff0c T的类型不能是Scalar 应为Vec3b xff0c 否则颜色修改失败 C 代码 xff1a Mat labs 61 new Mat int counts
  • VSCode idea 配置xml文件的dtd约束文件

    如上图配置XML文件的智能提示功能通过dtd文件 xff1a 1 通过VSCode 的扩展功能下载XML插件 xff08 注意 xff1a 插件内是包含dtd文件配置功能 xff09 配置方式 xff1a 1 DOCTYPE xff1a l
  • 关于0xAA和0x55

    许多串口通讯中测试或握手信号使用AA或55这两个特殊的十六进制数 xff0c 在许多PIC内部的 EEPROM 改写也使用这两个数作为敲门砖 xff0c 初学者可能不解何为 xff0c 其实如果将这两个数展开成二进制就可明白为什么 xff1
  • APS .Net MVC 之APIController与Controller的区别

    APIControllerController开发模式WebAPIMVC命名空间System Web HttpSystem Web Mvc返回方式json text或者xml texthtml textaction的默认请求方式postpo
  • DBeaver连接informix数据库乱码

    在工具栏选择数据库 驱动管理 informix编辑 xff0c 示例URL中添加NEWCODESET 61 utf8 8859 1 819 CLIENT LOCALE 61 en US utf8 DB LOCALE 61 en US 885
  • c语言——http编程

    HTTP协议简介 超文本传输协议是一种用于分布式 协作式和超媒体信息系统的应用层协议 HTTP是一个客户端终端 xff08 用户 xff09 和服务器端 xff08 网站 xff09 请求和应答的标准 xff08 一般基于TCP xff09
  • 串口开发之环形缓冲区

    01 简介 串口的基本应用 xff0c 使用串口中断接收数据 xff0c 串口中断发送回包 xff08 一般可以使用非中断形式发送回包 xff0c 在数据接收不频繁的应用中 串口接收中断保证串口数据及时响应 xff0c 使用非中断方式发送回
  • stl中的智能指针类详解

    C 43 43 98 03的尝试 std xff1a xff1a auto ptr C 43 43 11标准废弃了std xff1a xff1a auto ptr xff08 在C 43 43 17标准中被移除 xff09 xff0c 取而
  • 对于ROS的工作空间的理解(一)

    对于每一个任务 xff0c 可以在根目录下为它分配一个工作空间 mkdir p catkin ws src xff08 src 源码 xff09 cd catkin ws catkin make 编译 xff0c 生成devel xff08
  • stc-isp协议

    一 数据封装格式 包头 标示 数据包长度 命令字 内容 校验 包尾 1 包头 xff1a 2字节 xff0c 固定为 xff1a 0x46 xff0c 0xB9 2 标示 xff1a 1字节 xff0c 分两种 xff0c ARM发给MCU
  • 干货!串口通讯的起始、数据、停止位都是怎么分配的?

    串口是串行接口 xff08 serial port xff09 的简称 xff0c 也称为串行通信接口或COM接口 串口通信是指采用串行通信协议 xff08 serial communication xff09 在一条信号线上将数据一个比特
  • Linux 下char转换为wchar_t(窄字符转换位宽字符)

    LInux下使用mbstowcs函数可以将char转化为wchar t 函数含义 xff1a convert a multibyte string to a wide char string 说明 xff1a The behaviour o
  • Linux服务器 安装Pytorch GPU版本

    实验室服务器重做系统之后 xff0c 之间搭建的Python环境已甚嚣尘上 xff0c 只好从头再来 但是过程中遇到很多莫名其妙的bug xff0c 特此立章记录 xff0c 望对他人有所帮助 作为一个深度学习的初学者 xff0c 个人对所
  • 鼠标悬停效果 PPT制作

    鼠标悬停效果实现 在制作PPT时 xff0c 有时候需要实现鼠标的悬停效果 xff0c 即将鼠标放置在某个按钮或图片上 xff0c 实现动态变化的效果 目标是 xff1a 当鼠标悬停在一些人物名字上时 xff0c 出现该人物的个人信息 具体
  • 谷歌学术——下载论文

    一些同学在找论文的时候 xff0c 在学校数据库找不到 xff0c 因此可以使用谷歌学术来找 但是国内被墙了 xff0c 无法访问 xff0c 所以可以使用镜像服务器 首先进入谷歌镜像 xff1a 镜像网站 xff08 https ac s
  • Ubuntu 22.04 安装vm-tools

    安装过程一路心酸 xff0c 大家慎重 在Vmware中新建虚拟机之后 xff0c 发现没有办法传输文件和进行随窗口的视图变化 xff0c 打算安装vm tools 但是在Ubuntu 22 04 中 xff0c 如果使用Vmware自带的
  • LD文件 详解

    ld 组合了许多对象文件和归档文件 xff0c 重新定位它们的数据并绑定符号引用 通常编译程序的最后一步是运行 ld 每个可加载或可分配的输出节都有两个地址 第一个是 VMA xff0c 即虚拟内存地址 这是运行输出文件时该节所拥有的地址
  • 【Linux0.11 源码历险记 2】《保护模式》

    继续跟着stup s 来看 xff1a lidt idt 48 load idt with 0 0 lgdt gdt 48 load gdt with whatever appropriate idt 48 word 0 idt limit
  • 【Linux0.11 源码历险记 3】《开启分页》

    下面我们就正式进入head s 的代码 xff1a text globl idt gdt pg dir tmp floppy area pg dir startup 32 movl 0x10 eax mov ax ds mov ax es