Linux-0.11 boot目录head.s详解

news2024/11/26 16:30:38

Linux-0.11 boot目录head.s详解

模块简介

在head.s中,操作系统主要做了如下几件事:

  • 重新设置中断描述符和全局描述符
  • 检查A20地址线是否开启
  • 检查数学协处理器
  • 初始化页表并开启分页
  • 跳转到main函数执行

过程详解

重新设置IDT和GDT

在setup.s中我们已经设置过了IDT和GDT, 为什么还要再设置一遍?

因为setup.s中设置的IDT和GDT后面会被覆盖,因此在head.S中会重新设置一遍。

startup_32:
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	mov %ax,%gs
	lss stack_start,%esp
	call setup_idt     !设置中断
	call setup_gdt     !设置全局描述符表
	movl $0x10,%eax		# reload all the segment registers
	mov %ax,%ds		# after changing gdt. CS was already
	mov %ax,%es		# reloaded in 'setup_gdt'
	mov %ax,%fs
	mov %ax,%gs
	lss stack_start,%esp

中断门描述符的格式如下所示:

中断门描述符格式

检查A20地址线是否开启

下面用于检测A20地址线是否已经开启。

	xorl %eax,%eax
1:	incl %eax		# check that A20 really IS enabled
	movl %eax,0x000000	# loop forever if it isn't
	cmpl %eax,0x100000
	je 1b

检查数学协处理器

下面用于检查数学协处理器芯片是否存在

	movl %cr0,%eax		# check math chip
	andl $0x80000011,%eax	# Save PG,PE,ET
/* "orl $0x10020,%eax" here for 486 might be good */
	orl $2,%eax		# set MP
	movl %eax,%cr0
	call check_x87
	jmp after_page_tables

/*
 * We depend on ET to be correct. This checks for 287/387.
 */
check_x87:
	fninit     !向协处理发出初始化命令
	fstsw %ax  !取协处理器状态字到ax寄存器中
	cmpb $0,%al
	je 1f			/* no coprocessor: have to set bits */
	movl %cr0,%eax
	xorl $6,%eax		/* reset MP, set EM */
	movl %eax,%cr0
	ret

初始化页表并开启分页

下面这里将进行页表的安装,安装的过程参考下面这张图:
页表的设置

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

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
	cld
	xorl %eax,%eax		 !设置页目录表基址寄存器cr3的值
	movl %eax,%cr3		
	movl %cr0,%eax       !设置启动使用分页处理
	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */
	ret			/* this also flushes prefetch-queue */

跳转到main函数执行

在setup_paging执行完毕之后,会通过ret返回,ret指令会将栈顶的内容弹出到PC指针中去执行。此时esp指向的位置存放的是main函数的地址。因此接下来会执行main函数。

注意到在将main入栈时,还一同入栈了一些其他参数

	pushl $0		# These are the parameters to main :-)
	pushl $0
	pushl $0
	pushl $L6

这里就需要回顾一下c语言的调用规约,如下图所示:

启动中内存分布变化

因此这里可以得到L6是main函数的返回值。立即数0,0,0将会被作为main函数的入参。

接下来再看下面的代码就很清晰了,实际就是在建立好页表的映射关系后,就开始跳转到main函数去执行了(init/main.c)。

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

setup_paging:
   ...
   ret

Q & A

setup_paging在建立页表时会将head.s的部分代码覆盖,怎么保证不会把正在执行的代码覆盖?

可以通过反汇编查看一下system模块的内存分布

objdump -d tools/system

如下所示:

00000000 <pg_dir>:
       0:	b8 10 00 00 00       	mov    $0x10,%eax
       5:	8e d8                	mov    %eax,%ds
	   ...
0000005a <check_x87>:
      5a:	db e3                	fninit 
      5c:	9b df e0             	fstsw  %ax
      5f:	3c 00                	cmp    $0x0,%al
	  ...
00000071 <setup_idt>:
      71:	8d 15 28 54 00 00    	lea    0x5428,%edx
      77:	b8 00 00 08 00       	mov    $0x80000,%eax
	  ...
0000008e <rp_sidt>:
      8e:	89 07                	mov    %eax,(%edi)
      90:	89 57 04             	mov    %edx,0x4(%edi)
	  ...
000000a1 <setup_gdt>:
      a1:	0f 01 15 b2 54 00 00 	lgdtl  0x54b2
      a8:	c3                   	ret    
	...
00001000 <pg0>:
	...

00002000 <pg1>:
	...

00003000 <pg2>:
	...

00004000 <pg3>:
	...
00005000 <tmp_floppy_area>:
	...
00005400 <after_page_tables>:
    5400:	6a 00                	push   $0x0
    5402:	6a 00                	push   $0x0
	...
00005412 <L6>:
    5412:	eb fe                	jmp    5412 <L6>
00005414 <int_msg>:
    5414:	55                   	push   %ebp
    5415:	6e                   	outsb  %ds:(%esi),(%dx)
	...
00005428 <ignore_int>:
    5428:	50                   	push   %eax
    5429:	51                   	push   %ecx
	...
0000544e <setup_paging>:
    544e:	b9 00 14 00 00       	mov    $0x1400,%ecx
    5453:	31 c0                	xor    %eax,%eax
    5455:	31 ff                	xor  
	...
000054aa <idt_descr>:
    54aa:	ff 07                	incl   (%edi)
    54ac:	b8 54 00 00 00       	mov    $0x54,%eax
	...

000054b2 <gdt_descr>:
    54b2:	ff 07                	incl   (%edi)
    54b4:	b8                   	.byte 0xb8
    54b5:	5c                   	pop    %esp
	...

000054b8 <idt>:
	...

00005cb8 <gdt>:
	...
    5cc0:	ff 0f                	decl   (%edi)

可以看到代码标号setup_page的起始地址是0000544e,而内存页表和页目录表的地址范围是0x0000-0x5000。因此当程序执行到setup_page时,将建立页目录表和页表, 这将会覆盖0x0000-0x5000的部分代码,即pg_dir,check_x87,setup_idt,rp_sidt,setup_gdt, 并不会覆盖到setup_page的代码,head.s在代码的分布计算上确实是费了一番功夫。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/578104.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python逆序排列:从入门到精通

Python 逆序排列&#xff1a;从入门到精通 Python 语言因其简单易学、性能高效、多平台支持等优点而备受青睐。而在 Python 中进行逆序排列操作是我们经常需要用到的一个功能&#xff0c;本篇文章将详细介绍 Python 中的逆序排列操作。 什么是逆序排列&#xff1f; 逆序排列…

chatgpt赋能python:Python行转列:如何高效地处理大数据集

Python行转列&#xff1a;如何高效地处理大数据集 Python是一种广泛使用的编程语言&#xff0c;最初用于Web开发&#xff0c;如今已成为专业开发、科学计算和数据分析等领域的一种首选语言。Python非常方便&#xff0c;尤其是在处理大数据集时。本文将介绍如何使用Python将行数…

Protobuf协议初级详解(python使用)从安装到序列化-反序列化

教程 一、前言二、效果三、教程1&#xff09;安装2&#xff09;使用1.创建.proto文件2.proto语法3.protoc.exe文件编译.proto语法文件4.序列化5.反序列化 四、借鉴 一、前言 Protobuf是一种轻便高效的结构化数据存储格式&#xff0c;可以用于结构化数据序列化&#xff0c;很适合…

chatgpt赋能python:Python随机抽取:提高数据样本代表性的利器

Python随机抽取&#xff1a;提高数据样本代表性的利器 在数据分析和机器学习领域&#xff0c;我们经常需要对数据进行随机抽样以获得更有代表性的数据集。而Python提供了很多方便易用的函数和库&#xff0c;使得数据抽样变得更加简单和高效。 random库&#xff1a;生成随机序…

chatgpt赋能python:Python随机选择数字

Python随机选择数字 如果你正在寻找一种简单的方法在Python中选择随机数字&#xff0c;那么你来对地方了&#xff01;在这篇文章里&#xff0c;我们将介绍Python的内置模块random和它的方法来选择随机数字。 什么是Python的Random模块&#xff1f; Python的random模块是一个…

chatgpt赋能python:Python中的随机选择:介绍和应用

Python中的随机选择&#xff1a;介绍和应用 Python是一种流行的编程语言&#xff0c;广泛应用于数据科学、人工智能和网络开发等领域。Python中有许多方便的功能和库&#xff0c;使得编程工作更加轻松和高效。其中一个重要的库是random模块&#xff0c;它可以用来生成随机数和…

横向移动-传递攻击SMB服务利用psexecsmbexec

win2012以上版本&#xff0c;关闭了wdigest 或者安装了 KB287199补丁。无法获取明文密码 总的来说就是win2012后无法获取明文密码 解决办法就是&#xff1a; 1.可以利用哈希hash传递&#xff08;pth&#xff0c;ptk等进行移动&#xff09; 2.利用其他服务协议&#xff08;S…

chatgpt赋能python:【Python实例教程】如何使用Python计算长方形面积

【Python实例教程】如何使用Python计算长方形面积 Python是一种广泛使用的高级编程语言&#xff0c;因其易学易用的特性而备受推崇。Python在编写程序时也可以很方便地进行数学计算。本篇文章将介绍如何使用Python计算长方形的面积&#xff0c;希望对Python初学者有所帮助。 …

访客管理系统:Lobby Track Crack

Lobbytrack桌面 for 微软视窗 一个强大的、功能齐全的现场访客管理系统解决方案。在本地管理您的数据&#xff0c;网络工作站一起配置访客管理流程的各个方面。 扩展您的系统将本地 Web 模块 添加到您的 Lobbytrack 桌面系统&#xff0c;并允许您的员工使用本地 Intranet 上的 …

【Cookie和Session】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、Cookie和Session&#xff08;面试常考&…

目标检测YOLO实战应用案例100讲-基于深度学习的无人机航拍图像目标检测算法研究与应用

基于深度学习的无人机航拍图像目标检测算法研究与应用 无人机是无线遥控装置和内置的程序控制装置操纵,亦或由车载计算机完全地 或间歇地规律操控的不载人飞机。无人机的地面航拍成像在军事探察、地质勘探、 公安侦查等领域[1-2]得到广泛应用。在军事领域,能够通过无人机进行…

chatgpt赋能Python-python_读取png

前言 Python是一种高级编程语言&#xff0c;尤为擅长处理数据科学和机器学习方面的应用。PNG&#xff08;Portable Network Graphics&#xff09;是一种流行的图像格式&#xff0c;它使用无损压缩技术来存储图像数据。在本文中&#xff0c;我们将介绍如何使用Python读取PNG图像…

SAP MM采购申请审批-成本中心

抬头审批的采购申请中行项目里的成本中心必须是同一个! 1、创建特性成本中心CT04 2、把特性分配给类CL02 3、维护分类审批策略 这些成本中心都可以使用&#xff0c;如果是单项就需要再CT04维护成多值。 如下采购申请&#xff0c;系统找不到审批策略, 2个行项目中&#xff0c;成…

【C语言】简单排序:冒泡排序和选择排序(含图解)

文章目录 1. 冒泡排序1.1 思想1.2 代码实现 2. 选择排序2.1 思想2.2 代码实现 1. 冒泡排序 1.1 思想 选择排序算法思想&#xff1a;以升序为例 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。对每一对相邻元素作同样的工作&#xff0c;从开始第一对到结…

了解list

list 1. list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.5 list modifiers1. resize2. push_back/pop_back/push_front/pop_front3. insert /erase4. swap/clear 1.2.6 list operati…

chatgpt赋能python:Python中的数字转换

Python中的数字转换 在Python中&#xff0c;数字转换是一项非常基础但是非常重要的任务。无论您是在进行数据分析、机器学习还是编写Web应用程序&#xff0c;数字转换都是必不可少的。在这篇文章中&#xff0c;我们将介绍Python中的数字转换并提供一些实用的示例。 将字符串转…

Unity之SpriteShapeController

Detail&#xff1a;精灵形状的质量 高中低三种质量 Is Open Ended&#xff1a;是否是开放的&#xff0c;不封闭的 Adaptive UV&#xff1a;自适应UV&#xff0c;如果开启&#xff0c;会自动帮助我们判断是平铺还是拉伸 开启后只有宽度够才会平铺&#xff0c;如果宽度不够会拉…

micropython固件编译——把自己的py库添加进固件

目录 0. 前言1. 编写自己库的代码2. 移植库3. 验证 0. 前言 本节编译自己写的py库&#xff0c;增强移植性&#xff0c;往后烧录自己的固件即可轻易移植代码 没装好环境或者没有基础可以先看看这个&#xff1a; Ubuntu下ESP-IDF的环境搭建 Ubuntu下编译esp32micropython固件编…

antV 事件多次触发问题,解绑

由于最近刚刚接触 antV - 数据可视化,对于他的事件应用还比较陌生,在应用中莫名其妙多次调用,想了很多方式如节流……,但是没有用。 业务介绍 当我点击流程图中的某一项进行提示,每次双击都会递增调用。 解决过程 当时想着用节流的方式,但是很遗憾,他还是疯狂递增调用…

Go语言的命令

常用命令 假如你已安装了golang环境&#xff0c;你可以在命令行执行go命令查看相关的Go语言命令&#xff1a; Go语言是一门编译型语言&#xff0c;通过命令行工具来编译、运行和管理代码。以下是Go语言的一些常用命令及其用法&#xff1a; go run&#xff1a;用于编译并直接…