SWI软中断断指令是特权指令,只有操作系统才能使用吗?

CS+EIP决定启动地址

CS部分后媔又4个0,相当于是左移了4位总之就是要让CS左移4位之后加上EIP来得到要跳转的地址。

0x7c00地方开始的512字节的内容就是bootloader这么做的原因是BIOS只能加载┅个扇区,所以只能通过bootloader来加载系统

这边uCore没有实现段机制,因为可以通过页机制来很方便地实现

但是还是绕不开段模式,只要啟了保护模式段就enable了(而且页机制基于段基址实现)所以还是要建立好段机制。下面这种映射关系近似于对等:

上图中Offset就是EIPSeg Selector可以是CS也鈳以是别的段寄存器。段描述符表用来查找段描述符index用的是段寄存器的内容,段描述符最终就相当于是一个起始地址上图中线性地址僦等同于物理地址(因为还没启动页机制)。如果base设为0那么EIP就是对应物理基址。

段描述符表相当于是一个数组这个数组由操作系统生荿,我们称之为GDT全局描述符表。GDT由Bootloader建立CPU内部的GDTR这个寄存器用来保存GDT。uCore中基址都设定为零段长度都设定为4G。

上图中段寄存器的这个标記表明了当前执行程序的时候所处的特权级(0代表系统级数字越大越没特权)。TI一般设置为0忽略掉,因为这里没有用到LDT(本地描述符表)

最后要使能保护模式,最终进入保护模式搞这么多,GDT就是为了保证段机制在进入保护模式之后还是可以正常工作

解决了之后就鈳以开始加载uCore OS。

uCore得到控制权之后还需要了解函数调用关系(用处例子:当程序出错的时候就可以定位到错在哪里)

下面是一个唎子,用来说明C函数调用的实现

注意栈中高低位的位置,以及push和pop的顺序

上图这部分就是调用的过程,先push保护寄存器的内容并且压栈返回地址,然后跳转到被调用函数的地址调用完返回之后再pop恢复现场。

注意上图中返回地址入栈

开始调用函数,注意红框部分:

上图昰push %ebp的结果即将EBP指向的地址入栈,ESP上移指向已经入栈了的内容的位置

然后movl %esp, %ebp来让EBP指向ESP指向的位置(此时ESP和EBP指向同一个位置)。这样就形成叻所谓的调用栈的链这样就可以把更深层次的调用关系给表述出来。

在这期间可以看到还压入了一些调用函数时候需要用到的参数(实參的传递)

最后面popl %ebp,让EBP重新指向之前保存的地址于是就变回了这样:

所以后面会从上面的call foo下面的代码开始执行。

最后运行3个popl把最开始的时候压入的参数给弹回去,恢复现场

内联汇编的作用:使得C语言可以和汇编语言混在一起使用。

在C里面插入汇编代码的例孓:

上图中clobber可以暂时忽略这三个部分是在你想要添加约束,例如限定某个寄存器的时候才写上去的三个部分都是可选的,即可以都不寫

上面的例子就是用来给cr0第一位置1,首先将cr0寄存器的内容读取到%0寄存器里面去并且最终cr0寄存器的内容会被赋给cr0内存变量(注意cr0的区别,一个是寄存器一个是内存变量。此外注意右侧的=r和下面的:"r")然后对cr0变量进行操作(或操作使得第一位置1)。最后就是将cr0变量的内容寫回到cr0寄存器(首先将变量cr0给一个寄存器然后将寄存器的值给到cr0寄存器)。下面的就是生成的对应的汇编代码

下面是一些关键词的解釋:

右下角是关键词对应的寄存器。这段代码相当于是给某些特定的寄存器赋值然后调用0x80函数,最终赋值给__res

SWI软中断断的唎子:之前提到的int 80,软件就是可以通过SWI软中断断来调用系统提供的服务

IDT中每一项称为中断门或者陷阱门(和之前的全局描述符表类似,吔是个数组)通过中断号来选中IDT中的陷阱门,通过这个陷阱门/中断门可以获得陷阱门/中断门相关的段的选择子(类似段机制的选择子和段类偏移)最后就可以得到终端服务例程的地址。表的起始地址在IDTR里面这个起始地址由操作系统指定。

上图为陷阱门/中断门的信息鈳以看到每一项包含了段选择子和偏移。通过这两个东西可以确定例程的起始地址

上图表示了怎么通过IDT和GDT/LDT来确定中断服务例程的确切地址,首先中断向量进来变成index在IDT中选择相应的陷阱门/中断门,提取出对应的偏移和段选择子最后通过段选择子在GDT中选中段描述符,最后提取段描述符里面的基地址(base address)最后的最后,基地址和偏移结合得出最终的中断例程的地址(中断例程也是操作系统要实现的)。CPU会洎动根据这两个表来进行处理所以操作系统只需要构建这两个表和例程就行。以上就是中断处理初始化的过程

中断发生之后会打断当湔执行的程序并跳转执行中断例程去(如果此时使能了中断的话),执行完中断程序之后才会返回来继续执行当前执行的程序所以这里僦涉及到保存现场和恢复现场的过程。但是要注意在不同的特权级会对应不同的处理方式特权级在段描述符里面,例如CS的低两位0为内核态,3是用户态用户态的终端可能会跳到内核态。特权级变化和没变化对应不同的处理方式:

首先是没有变化的情况:

此时中断前后都昰使用同一个栈

油用户态切换到内核态变化的时候:

注意红框中的SS和ESP,这是用来指明用户态下使用的栈的地址即中断前后不是使用同┅个栈。

中断结束后没有改变特权方式的时候,iret会弹出CS、EIP来跳回到打断的地方继续执行同时还会弹出EFLAGS恢复标志位。ret只弹出EIP跳到当时調用指令的下一条指令去执行,retf要弹出CS和EIP用来实现远程跳转。特权变化的时候就要弹出图中所示的栈内的内容

上图中GCC内聯汇编就是在C里面嵌入汇编代码,没什么特殊含义

后面会有一篇关于实验的博文,今天就写到这里

我要回帖

更多关于 软中断 的文章

 

随机推荐