第六章-完善内核

news2024/9/22 15:28:47

Ⅰ.函数调用约定

首先,函数调用在处理器执行过程中实际是栈的切换,从当前执行任务的栈切换到另一个栈,但是切换过程中涉及到参数传递方式、参数传递顺序、栈的销毁等,因此在切换过程中需要明确函数调用约定

根据下面表可看出在函数调用过程中主要规定了参数入栈方式(根据栈先入后出原则,一般从右向左)、栈清理方式(被调用者清理-函数执行完了自己清理、调用者清理-调用返回后清理,实质就是将栈指针恢复调用之前)等。

在这里插入图片描述

以stdcall为例,说明调用全过程:

(1)从右到左入栈

(2)被调用函数栈清理

int subtract(int a, int b); //被调用者
int sub= subtract (3,2); //主调用者

主调用者:

;从右到左将参数入校
 push 2	;压入参数 b
 push 3	;压入参数 a
 call subtract	;调用函数 subtract

被调用者:

push ebp		;备份主调用者的栈
mov ebp, esp	;更新被调用者的栈指针esp
mov eax,[ebp+0x8]	;取a
add eax,[ebp+0x]	;取b
pop ebp				;恢复ebp
ret 8				;标识返回后ret+8,清理栈

在这里插入图片描述

以cdecl调用约定为例,说明调用全过程:

(1)从右到左入栈,允许参数不固定

(2)主调用函数栈清理

int subtract(int a, int b); //被调用者
int sub= subtract (3,2); //主调用者

主调用者:

;从右到左将参数入校
 push 2	;压入参数 b
 push 3	;压入参数 a
 call subtract	;调用函数 subtract
 add esp, 8		; 回收(清理)栈空间

被调用者

push ebp		;备份主调用者的栈
mov ebp, esp	;更新被调用者的栈指针esp
mov eax,[ebp+0x8]	;取a
add eax,[ebp+0x]	;取b
pop ebp				;恢复ebp
ret					;恢复ebp

Ⅱ.汇编语言和C语言混合模型

汇编语言和 C 语言混合编程可分为两大类。
(1)单独的汇编代码文件与单独的 C 语言文件分别编译成目标文件后, 一起链接成可执行程序。
(2)在 C 语言中嵌入汇编代码,直接编译生成可执行程序。

BIOS中断向量表的每一个中断号对应一个功能,而中断描述符表的每一个中断号可以对应不同的子功能。系统调用的入口只有一个,即第 0x80 号中断,具体的子功能在寄存器 eax中单独指定 。

1.系统调用
(1)调用“系统调用”有两种方式。
  1. 将系统调用指令封装为 c 库函数,通过库函数进行系统调用,操作简单。
  2. 不依赖任何库函数,直接通过汇编指令 int 与操作系统通信。

当输入的参数小于等于 5 个时, Linux 用寄存器传递参数。当参数个数大于 5 个时,把参数按照顺序放入连续的内存区域,并将该区域的首地址放到 ebx 寄存器。这里我们只演示参数小于等于 5 个的情况。

eax 寄存器用来存储子功能号(寄存器 eip 、 ebp 、 esp 是不能使用的)。 5 个参数存放在以下寄存器中,传送参数的顺序如下。
(1) ebx 存储第 1 个参数。
(2) ecx 存储第 2 个参数。
(3) edx 存储第 3 个参数。
(4) esi 存储第 4 个参数。
(5) edi 存储第 5 个参数。

2.内联汇编
(1)含义以及语法介绍

内联汇编:在C语言中嵌入汇编代码。针对不同平台,使用不同的汇编代码规范,譬如windows下使用Intel语法,而在Linux下,使用AT&T语法。Intel语法更符合高级语言编写风格,如mov eax, ebx表示eax=ebx;而AT&T语法更符合处理器处理方式,mov eax, ebx表示ebx=eax。

在这里插入图片描述

AT&T寻址方式

segreg (段基址): base address(offset_address,index,size) 等价于segreg (段基址): base_address+ offset_address+ index*size

(2)内联汇编形式
基本内联汇编
asm [volatile] (”assembly code")  

下面说下 assembly eode 的规则
( l )指令必须用双引号引起来,无论双引号中是一条指令或多条指令。
(2 ) 一对双引号不能跨行,如果跨行需要在结尾用反斜杠气’转义。
(3 )指令之间用分号";"、换行符’\n’或换行符加制表符’\n\t’分隔。那么就不能再内联汇编里写注释了

即使是指令分布在多个双引号中, gcc最终也要把它们合并到一起来处理,合并之后,指令间必须要有分隔符。所以,当指令在多个双引号中时,除最后一个双引号外,其余双引号中的代码最后 一定要有分隔符。

小试牛刀:在C语言中内嵌汇编,实现打印字符串功能:

char str[10] = "hello world\n";
int len = 10;
int ret = 0;	
void main(void){
	asm volatile ("pusha;	# 将所有变量压入栈"
		"movl $4,%eax;		# 中断子功能号"
		"movl $1,%ebx;		# fd=1表示通过stdout输出"
		"movl str,%ecx;"
		"movl len,%edx;"
		"int $0x80;"
		"movl %eax, ret;"
		"popa;"
		);
	printf("result is : %d", ret);
}

等同于

char str[10] = "hello world\n";
int len = 10;
int ret = 0;	
void main(void){
	asm volatile ("pusha;\
		movl $4,%eax;\
		movl $1,%ebx;\
		movl str,%ecx;\
		movl len,%edx;\
		int $0x80;\
		movl %eax, ret;\
		popa;\
		);
	printf("result is : %d", ret);
}
扩展内联汇编

基本内联汇编可能只嵌入C语言的一部分,编译后需要分配寄存器资源,那么如何确保汇编调用的寄存器未被占用?此外,若汇编代码需要用到C语言变量,如何找到可用的寄存器保存操作数呢?于是,衍生了扩展内联汇编。具体方法类似让内联汇编像函数一样调用

类似。通过添加约束,规定了操作数使用的寄存器

asm volatile {"assembly code" : output : input : clobber/modify}
  • input可引入计算过程中涉及到的c变量,使用规则为:“[操作数修饰符]约束名”(C 变量名)
  • output将计算结果保存到c变量,使用规则为:“操作数修饰符约束名”(C 变量名)
  • clobber/modify :汇编代码执行后会破坏一些内存或寄存器资源,通过此项通知编译器,可能造成寄
    存器或内存数据的破坏,这样 gee 就知道哪些寄存器或内存需要提前保护起来
(3)扩展内联汇编约束

总共包括四大类约束:寄存器约束、内存约束、

(3.1)寄存器约束

寄存器约束就是要求 gcc使用哪个寄存器,将 input 或 output 中变量约束在某个寄存器中。常见的寄存器约束有:
a:表示寄存器 eax/ax/al
b:表示寄存器 ebx/bx/bl
c:表示寄存器 eex/ex/cl
d:表示寄存器 edx/dx/dl

D :表示寄存器 edi/di
S :表示寄存器 esi/si
q:表示任意这 4 个通用寄存器之-: eax/ebx/ecx/edx
r:表示任意这 6 个通用寄存器之一 :eax/ebx/ecx/edxesi/edi
g:表示可以存放到任意地点(寄存器和内存)。相当于除了同 q 一样外,还可以让 gcc 安排在内存中
A :把 eax和 edx 组合成 64 位整数
f:表示浮点寄存器
t :表示第 1 个浮点寄存器
u:表示第 2 个浮点寄存器

示例:加法操作

基本内联汇编

#include <stdio.h>
int in_a = 1, in_b = 2;
int ret;
void main(void){
	asm volatile {"pusha;\
		movl in_a,%eax;\
		movl in_b,%ebx;\
		addl %ebx,%eax;\
		movl %eax,ret;\
		popa;"}
	printf("result is %d", ret);
}

扩展内联汇编

#include <stdio.h>
int in_a = 1, in_b = 2;
int ret;
void main(void){
	asm volatile {"addl %%ebx,%%eax":"=a"(ret):"a"(in_a),"b"(in_b)}
	printf("result is %d", ret);
}

扩展内联汇编中寄存器前缀是两个%。

input:a表示用eax存储in_a,b表示用ebx存储in_b

output:=号表示操作数类型修饰符,表示只写,a表示eax

(3.2)内存约束

内存约束是要求 gcc 直接将位于 input 和 output 中的 C 变量的内存地址作为内联汇编代码的操作数,不需要寄存器做中转,直接进行内存读写,也就是汇编代码的操作数是 C 变量的指针。

(3.3)立即数约束

立即数即常数,此约束要求 gee 在传值的时候不通过内存和寄存器,直接作为立即数传给汇编代码 。由于立即数不是变量,只能作为右值,所以只能放在 input 中。

i:表示操作数为整数立即数
F:表示操作数为浮点数立即数
I :表示操作数为 0~ 31 之间的立即数
J:表示操作数为 0~ 63 之间的立即数
N:表示操作数为 0~255 之间的立即数
O:表示操作数为 0~32 之间的立即数
X:表示操作数为任何类型立即数

(3.4)通用约束

0~ 9:此约束只用在 input 部分,但表示可与 output 和 input 中第 n 个操作数用相同的寄存器或内存 。

总结:

首先在实模式下配置好硬盘读写的配置,设置相应的LAB地址、读写操作、读入状态寄存器,确保MBR能够从指定的硬盘地址加载loader.s到内存中。

执行loader.s,主要完成实模式切换到保护模式,设置内存管理方式(分页或分段)。模式切换:设置gdt表;设置cr0寄存器,开启A20地址线。内存管理方式设置:初始为分段,页面置换以段为单位,但是在小内存的情况下,以段为单位进行置换也可能会出现内存不够放置段的情况,因此想要将段划分为更小的单位——页。设置cr3 gdt表存储寄存器和cr0寄存器;设置页目录表、页表、页表项;重新放置gdt。进入保护模式后,需要从新设置gdt地址,因为实模式下内存空间只有1MB,在保护模式下,0地址存放的是内核,为了保证内核有足够的空间,所以需要将gdt表重新布局。

执行main.c。完成内核映像加载到虚拟内存的3G高址空间,但是不能从3G开始,因为3G空间起始部分存放的是loader程序以及gdt表,根据loader最多不超过2000字节,通过计算后可以得到映像最合适的存放位置。

系统调用本质是中断,系统调用方式有两种:1.将系统调用的int指令封装在c中库函数供开发者使用;2.直接调用int指令与操作系统通信。

本文讲解了内联汇编的两种方式:基本内联汇编,扩展内联汇编。基本内联汇编存在缺点为,执行处寄存器状态未知以及可用寄存器信息未知,扩展内联汇编通过添加多种约束来保证汇编执行过程中使用的寄存器。

存的3G高址空间,但是不能从3G开始,因为3G空间起始部分存放的是loader程序以及gdt表,根据loader最多不超过2000字节,通过计算后可以得到映像最合适的存放位置。

系统调用本质是中断,系统调用方式有两种:1.将系统调用的int指令封装在c中库函数供开发者使用;2.直接调用int指令与操作系统通信。

本文讲解了内联汇编的两种方式:基本内联汇编,扩展内联汇编。基本内联汇编存在缺点为,执行处寄存器状态未知以及可用寄存器信息未知,扩展内联汇编通过添加多种约束来保证汇编执行过程中使用的寄存器。

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

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

相关文章

linux后台运行java项目/ jar包:nohup 命令

1.提出问题 我们把一个 SpringBoot 工程导出为 jar 包&#xff0c;jar 包上传到阿里云 ECS 服务器上&#xff0c;使用 java -jar xxx-xxx.jar 命令启动这个 SpringBoot 程序。此时我们本地的 xshell 客户端必须一直开着&#xff0c;一旦 xshell 客户端关闭&#xff0c;java -j…

Gin,Gorm实现Web计算器

目录 仓库链接0.PSP表格1. 成品展示1.基础运算2. 清零回退3.错误提示4.历史记录拓展功能1.前端可修改的利率计算器2.科学计算器3. 按钮切换不同计算器模式4.用户在一次运算后不清零继续输入操作符&#xff0c;替换表达式为上次答案 2.设计实现过程3.代码说明4.心路历程和收获 仓…

大模型/LLM的涌现能力

新浪张俊林–中国人工智能学会演讲 文章目录 什么是大模型的涌现能力LLM表现的涌现能力1. In Context Learning -- 情景学习2. CoT3. 其他涌现能力 LLM模型规模和涌现能力的关系模型训练中的顿悟现象&#xff1a;GrokkingLLM涌现能力的可能原因 什么是大模型的涌现能力 涌现&a…

message“: “CSRF token mismatch

tableData&#xff0c;noticeData 是两个长二维数组 $.ajax({url: "/admin/samproofing/confirmPieces",type: "POST",data: {"ym": ym1,"papertype":paper_type,"person_data": that.tableData,"notice_data": t…

Servlet入门

URL和URI&#xff1a; URL统一资源定位符&#xff0c;表示对外暴露的整个网址 URI统一资源标示符&#xff0c;表示资源的访问路径&#xff0c;与servlet绑定的地址 HTTP请求结构&#xff1a; HTTP请求包含三部分&#xff1a;请求行、请求头、请求体 请求行包含&#xff1a;请…

被替换掉的文件如何找回来?

当我们在编辑文件时&#xff0c;通常会直接保存而不是另存为新文件&#xff0c;这样会替换原始文件的信息。如果需要对原始文件进行二次编辑&#xff0c;情况就会比较复杂。那么被替换掉的文件还能找回来吗&#xff1f; 被替换的文件是否可以恢复&#xff1f; 这取决于替换原始…

【论文笔记】A theory of learning from different domains

防盗 https://www.cnblogs.com/setdong/p/17756127.html domain adaptation 领域理论方向的重要论文. 这篇笔记主要是推导文章中的定理, 还有分析定理的直观解释. 笔记中的章节号与论文中的保持一致. 1. Introduction domain adaptation 的设定介绍: 有两个域, source domain…

智慧空开让用电更安全、管理更智能——电脑APP远程控制开合闸

安科瑞 崔丽洁 01 什么是低压断路器&#xff1f;低压断路器的定义是&#xff1a;能够接通、承载及分断正常电路条件下的电流&#xff0c;也能在规定的非正常电路条件&#xff08;过载、短路、特别是短路&#xff09;下接通、承载一定时间和分断电流的开关电器。 断路器的分类&…

go语言教程4:switch和map

文章目录 switchswitch匹配字典 go语言教程&#xff1a;安装入门➡️for循环➡️数组、切片和指针 switch和map&#xff0c;一个是控制流&#xff0c;一个是数据结构&#xff0c;之所以把两个不同类型的知识点放在一起讲解&#xff0c;是因为二者有着极其相似的运行逻辑&#…

WSL+vscode配置miniob环境

1.配置WSL Windows Subsystem for Linux入门&#xff1a;安装配置图形界面中文环境vscode wu-kan 2.获取源码 找个位置Git Bash然后拉取代码 git clone https://github.com/oceanbase/miniob.git 3.安装相关依赖 https://gitee.com/liangcha-xyy/source/blob/master/how…

Spring Boot Bean 注入的常用方式教程

Spring Boot Bean 注入是一种将依赖对象引入到应用程序组件中的机制&#xff0c;它有助于实现松耦合和可测试的代码。这种注入方式允许我们将依赖关系委托给 Spring 容器来管理&#xff0c;从而提高了代码的可维护性和可读性。Spring Boot 提供了多种 Bean 注入方式&#xff0c…

qt判断当前日期的当月的最后一天是几号

1、拖个dateTimeEdit在界面上&#xff0c;同时来判断输入的时间的最后一天的日期是什么&#xff1f; int year,month;int monthArr[12]{31,28,31,30,31,30,31,31,30,31,30,31};QDateTime time ui->dateTimeEdit->dateTime();year time.toString("yyyy").toIn…

C++入门介绍

1.C入门知识 以下是一些 C 入门知识&#xff1a; C 是一种面向对象的编程语言&#xff0c;它具有高效、灵活、可移植性好等特点 C 中的基本数据类型包括整型、浮点型、字符型等 C 中的控制语句包括条件语句&#xff08;if、else&#xff09;、循环语句&#xff08;for、while、…

飞凌嵌入式成为“龙芯生态伙伴计划”认证级企业!

近日&#xff0c;飞凌嵌入式正式成为“龙芯生态伙伴计划”认证企业&#xff0c;标志着飞凌嵌入式与龙芯中科的紧密型战略合作伙伴关系正式建立&#xff01; “龙芯生态伙伴计划”由龙芯中科主导发起&#xff0c;旨在推动龙芯生态企业基于龙芯平台开发产品&#xff0c;丰富龙芯…

MyBatisPlus属性自动填充和乐观锁插件+查询删除操作+整合SpringBoot出现问题解决

属性字段自动填充 一、实体类和数据表添加两个字段&#xff08;属性&#xff09; 表&#xff1a;create_tiem/update_time 实体类&#xff1a;createTime/updateTime 二、实体类中属性进行注解添加 TableField(fillFieldFill.INSERT) private Date createTime;TableField(f…

DC2DC电源设计注意事项--1,Feedback

电源采集图如下图 Feedback 采集电压点应该在靠近负载侧。这样可以减少大电流导线导致的电压差&#xff0c;真实反应输出电压值 FB_1P21采集电路靠近芯片侧&#xff0c; 2.1&#xff0c;采集分压电路上侧为Vout Vnoise, 那么一分压就噪声就小了。假如采集电路远离芯片侧&…

简洁多媒体影音库 Emby 中文最新 for mac

Emby是一款用于媒体服务器和媒体中心的软件平台。它允许用户将个人的音乐、电影、电视节目、照片和其他媒体文件组织和管理起来&#xff0c;并通过各种设备进行访问和流媒体播放。 以下是Emby可能提供的一些主要功能和特点&#xff1a; 媒体管理和组织&#xff1a;Emby允许用户…

蒙特卡洛方法的简单应用

蒙特卡洛方法的简单应用 圆周率估算 eastimate pi python version 3.11 RNG:np.random.random import os figure_save_path "file_fig" import warnings warnings.filterwarnings("error") import numpy as np np.random.seed(0) import matplotlib.pyp…

温度在线检测技术在电力电缆线路的应用

在电力电缆的日常运行检测中&#xff0c;针对电缆温度的状况&#xff0c;所采用的电力温度在线检测技术也得到了大范围的普及。电网系统中&#xff0c;其单位时间内可输送的电力能源受到其温度的变化影响。因此&#xff0c;采用更有效的方式实时检测电缆系统运行温度&#xff0…

虾皮商品链接获取虾皮商品详情数据(用 Python实现虾皮商品信息抓取)

在网页抓取方面&#xff0c;可以使用 Python、Java 等编程语言编写程序&#xff0c;通过模拟 HTTP 请求&#xff0c;获取虾皮网站上的商品页面。在数据提取方面&#xff0c;可以使用正则表达式、XPath 等方式从 HTML 代码中提取出有用的信息。值得注意的是&#xff0c;虾皮网站…