一、3.外部硬件中断与进入保护模式

外部硬件中断:处理器接两根线NMI传输非屏蔽中断(即无法屏蔽的中断)和INTR传输可屏蔽中断

image-20230731215800052

IR0到IR7优先级依次降低

image-20230731220027450

处理器中中断标志位起决定作用,IF为0时屏蔽所有INTR引脚来的信号都被屏蔽

image-20230731220202828

image-20230731220619331

BIOS创建中断向量表

image-20230731221247135

实时时钟和CMOS RAM

CMOS RAM中的日期和时间通常使用二进制形式的十进制编码(BCD)来表示

image-20230731222012037

实时时钟RTC电路可以发出的中断信号类型:

  • 周期性中断信号
  • 更新周期结束中断
  • 闹钟中断

周期性中断信号

以固定周期进行中断

image-20230731223058346

寄存器A指定时基和速率

image-20230801073234092

寄存器B控制周期性中断是否运行

image-20230731223445947

更新周期结束中断

更新周期:每隔一秒更新时间、检查数据有效性、检查闹钟、写回更新的数据

image-20230801073732792

image-20230801074008211

image-20230801074308231

闹钟中断

image-20230801074555454

实时时钟发出的中断信号的类型判断:

寄存器C只读,读取后自动清零

image-20230801074757680

程序中修改SS寄存器和修改SP寄存器的指令必须相邻,否则可能会在中间发生中断导致栈错误

安装中断处理过程

image-20230801081345297

SECTION code align=16 vstart=0           ;定义代码段(16字节对齐) 
new_int_0x70:...iret...
start:mov ax,[stack_segment]mov ss,axmov sp,ss_pointermov ax,[data_segment]mov ds,axmov al,0x70 ; 中断号0x70mov bl,4mul bl ; 中断号乘4得到中断向量表IVT中对应中断的入口地址所在的地址mov bx,axcli ; 关中断,防止中断发生push esmov ax,0x0000 ; IVT所在段的地址mov es,axmov word [es:bx],new_int_0x70 ;写入自定义的中断处理过程的偏移地址mov word [es:bx+2],cs ;写入自定义的中断处理过程的段地址pop es

启用更新周期结束中断

image-20230801084517320

    mov al,0x0b ; RTC寄存器Bor al,0x80 ;最高位置1,NMI引脚外接一个与门的输出,输入一个是端口0x70最高位的反相,另一个是NMI中断信号,置1可阻断NMI out 0x70,al ; 0x70为索引端口,用于指定CMOS RAM内的单元mov al,0x12 ;设置寄存器B,禁止周期性中断,开放更新结束后中断,BCD码,24小时制 0001_0010out 0x71,al ; 0x71为数据端口,将寄存器B的设置信息输出给寄存器Bmov al,0x0c ; RTC寄存器Cout 0x70,alin al,0x71 ;读RTC寄存器C,复位未决的中断状态in al,0xa1 ;读8259从片的IMR寄存器(中断屏蔽寄存器,0为允许1为屏蔽)and al,0xfe ;清除最低位,此位连接RTC,开放RTC中断out 0xa1,al ;写回此寄存器 sti ;重新开放中断 

image-20230801085043354

中断处理过程:

等待更新周期结束

SECTION code align=16 vstart=0 ;定义代码段(16字节对齐) 
new_int_0x70:push axpush bxpush cxpush dxpush es.w0:                                    mov al,0x0a ; 寄存器Aor al,0x80                          out 0x70,al ;阻断NMI。当然,通常是不必要的in al,0x71 ;读寄存器Atest al,0x80 ;本质是与操作,但是结果不保留,ZF为0表示测试位不是0,测试第7位UIP jnz .w0

更新周期时间段:

image-20230801091932411

读取BCD码的时间:

xor al,al ; 清零al,秒的内容在CMOS RAM中存放的地址为0x00
or al,0x80 ; 阻断NMI
out 0x70,al ; 索引端口
in al,0x71 ;读RTC当前时间(秒,8位)
push axmov al,2
or al,0x80
out 0x70,al
in al,0x71 ;读RTC当前时间(分,8位)
push axmov al,4
or al,0x80
out 0x70,al
in al,0x71 ;读RTC当前时间(时,8位)
push axmov al,0x0c ;寄存器C的索引。最高位为0,开放NMI 
out 0x70,al
in al,0x71 ;读一下RTC的寄存器C,清零寄存器C,否则只发生一次中断,因为已经把闹钟和周期性中断关闭了,所以不考虑 

BCD码转ASCII:

bcd_to_ascii:   ;BCD码转ASCII;输入:AL=bcd码,8位;输出:AX=asciimov ah,al ;分拆成两个数字 and al,0x0f ;仅保留低4位 add al,0x30 ;转换成ASCII shr ah,4 ;逻辑右移4位,保留高4位                 add ah,0x30ret

显示并退出中断:

pop ax ; 取出小时的BDC码
call bcd_to_ascii
mov bx,12*160 + 36*2 ;从屏幕上的12行36列开始显示,行号*80*2 + 列号*2 = 显存中的偏移地址mov [es:bx],ah
mov [es:bx+2],al ;显示两位小时数字mov [es:bx+4], ':' ;显示分隔符':'
not byte [es:bx+5] ;反转显示属性 pop ax
call bcd_to_ascii
mov [es:bx+6],ah
mov [es:bx+8],al ;显示两位分钟数字mov [es:bx+10], ':' ;显示分隔符':'
not byte [es:bx+11] ;反转显示属性pop ax
call bcd_to_ascii
mov [es:bx+12],ah
mov [es:bx+14],al ;显示两位小时数字mov al,0x20 ;中断结束命令EOI
out 0xa0,al ;向从片发送 
out 0x20,al ;向主片发送 pop es
pop dx
pop cx
pop bx
pop axiret

image-20230801094509408

image-20230801100011390

处理器进入低功耗状态:hlt指令,在该指令行停机,但能被外部中断唤醒并继续执行之后的代码

.idle:hlt ;使CPU进入低功耗状态,直到用中断唤醒not byte [12*160 + 33*2+1] ;反转显示属性 jmp .idle

内部中断:处理器内部中断,处理器直接到中断对应处理过程处执行代码

软中断:代码产生中断

  • int 中断号
  • int3,在调试时将原指令机器码改为0XCC(即int3)从而中断去处理调试相关程序,调试完改行后将0XCC改回原机器码
  • into溢出中断,标志寄存器OF为1时才进入中断处理过程

BIOS中断:

image-20230801114236090

ROM BIOS搜索C0000~E0000这个区域,当有55AA这字则执行对应外设的功能调用例程代码,这个代码初始化设备,并把设备的外部中断号放入中断向量表中

mov cx,msg_end-message ; 获取message的字符长度
mov bx,message.putc:mov ah,0x0e ; 0x0e命令mov al,[bx]int 0x10 ; 0x10中断,ah为0x0e,查bios中断表可知是显示字符(光标前移)功能,AL=字符,BL=前景色(图形模式)inc bx ; 选中下一个字符loop .putc.reps:mov ah,0x00int 0x16 ; 0x16中断,ah为0x00,从键盘读字符功能mov ah,0x0emov bl,0x07int 0x10 ; 显示字符中断jmp .reps

32位处理器的寄存器扩展和扩充

image-20230801121036460

段寄存器:CS, DS ES, FS, GS, SS,长度还是16位

  • 实模式:(段地址<<4)+偏移地址 最大10FFEF,8086只有20根地址线,只能访问FFFF,80386有32根地址线,可以访问到10FFEF,FFFF~10FFEF这个区域称为高位内存区(HMA)。虽然32位处理器有32根地址线,但是实模式下超出10FFEF的内存是无法访问的
  • 保护模式:在描述符表中登记每个段的各种信息。段寄存器选中一个描述符,处理器取出描述符段基地址,和程序中给出的偏移地址组合,得到完整的内存地址

image-20230801133018823

image-20230801133115598

在保护模式下,一个段想被访问就必须去登记

image-20230801140700998

image-20230801143839753

gdt_size         dw 0 ; 一个字
gdt_base         dd 0x00007e00     ;GDT的物理地址 一个双字;计算GDT所在的逻辑段地址 
mov ax,[cs:gdt_base+0x7c00]        ;低16位,主引导扇区开始是0x7c00,需要加上 
mov dx,[cs:gdt_base+0x7c00+0x02]   ;高16位 
mov bx,16        
div bx ; 右移4位
mov ds,ax ;逻辑段地址,令DS指向该段以进行操作
mov bx,dx ;逻辑偏移地址,段内起始偏移地址 

image-20230801144559603

image-20230801144740774

S=1时

image-20230801145148592

image-20230801145557487

段界限:低32位0 ~ 15,高32位16 ~ 19

image-20230801151805033

image-20230801152208667

G位:高双字的第23位,粒度,用于解释段界限的单位,G=0段界限以字节为单位,G=1以4k字节为单位

实际使用的段界限 = 描述符中的段界限 * 0x1000G + 0xFFF * G

P位:高双字的第15位,段存在位,P=10段不存在,访问报错

L位:高双字的第21位,64位代码段标志

D/B位:高双字的第22位,操作尺寸(是代码段时)/栈上部边界(是数据段时),D/B=0该段按16位进行操作,D/B=1该段按32位进行操作

AVL位:高双字的第20位,保留位

安装存储器的段描述符

;DS:BX指向GDT起始地址
;创建0#描述符,它是空描述符,这是处理器的要求
mov dword [bx+0x00],0x00
mov dword [bx+0x04],0x00  ;创建#1描述符,保护模式下的代码段描述符
mov dword [bx+0x08],0x7c0001ff     
mov dword [bx+0x0c],0x00409800 

image-20230801155048130

image-20230801160625233

;初始化描述符表寄存器GDTR
mov word [cs:gdt_size+0x7c00], 15 ;主引导程序从7c00开始,加上偏移量gdt_size,定位到描述符表的界限,两个描述符,8字节*2-1(总字节数减一)   lgdt [cs:gdt_size+0x7c00] ; 指定gdt_size的地址,取出6字节(2字节描述符表界限,4字节描述符表起始地址)赋给GDTR寄存器

打开A20地址线:为了使用到地址为0x100000以上的内存,开启第21条地址线(A20)

image-20230801171637640

in al, 0x92 ;南桥芯片内的0x92端口 
or al, 0000_0010B ; 第1位置1
out 0x92, al ;打开A20

进入保护模式:设置CR0寄存器的PE位(第0位)为1

cli ;保护模式下中断机制尚未建立,应禁止中断 
mov eax,cr0
or eax,1 ; 最低位PE置1
mov cr0,eax

保护模式下的内存访问:

image-20230801202936673

段选择器内容不再是逻辑段地址,而是称为段选择子

image-20230801203135251

image-20230801203507513

mov cx,00000000000_10_000B ;加载数据段选择子(0x10)
mov ds,cx ; 此时ds的描述符高速缓存器中存放目标段基地址mov byte [0x00],'P'  ; 使用ds的描述符高速缓存器存放的段地址进行内存访问(0xb800)

image-20230801203728349

实模式下:

image-20230801204741190

指令操作尺寸:一段指令的操作数的长度

image-20230802073408760

image-20230802073438301

image-20230802074842949

32位特有内存寻址:

image-20230802080025125

image-20230802080708673

image-20230802080920307

image-20230802080939610

image-20230802082706672

可以看到操作尺寸为16位数据和32位数据时,相同格式的汇编指令的机器指令相同

  • 16位操作尺寸允许8位或16位操作数,以及16位有效地址
  • 32位操作尺寸允许8位或32位操作数,以及32位有效地址
  • 32位处理器支持16位和32位操作尺寸
  • 同一时刻处理器只能按一种操作尺寸工作,这种操作尺寸称为默认操作尺寸

image-20230802083245476

指定默认操作尺寸:bits 16/32

image-20230802090756133

;创建#2描述符,保护模式下的代码段描述符(主引导程序)
mov dword [bx+0x08],0x7c0001ff ; D位是1,即用32位操作尺寸
mov dword [bx+0x0c],0x00409800 
...;以下进入保护模式... ...
jmp dword 0000_0000_0000_0010_0_00B:flush ;16位的描述符选择子:32位偏移,选择第3个描述符表项(主引导程序)
bits 32 ; 因为在描述符中选择32位操作尺寸,所以之后的代码需要默认尺寸32位来编译,在此之前的代码是按16位编译
flush:...

image-20230802085719860

;在创建描述符表或进行段选择时,都需要对描述符表进行操作,这时对DS赋值有两种方式,传统编译器编译结果不同
mov ds, ax ;16位操作尺寸,编译8E D8;32位操作尺寸,编译66 8E D8
mov ds, eax ;16位操作尺寸,编译66 8E D8;32位操作尺寸,编译8E D8
;在32位操作尺寸下优先选后者
;NASM编译两者结果无论什么操作尺寸,都是8E D8

修改段寄存器时的保护:

  1. 检查选择子的合法性image-20230802112158076
  2. 确认描述符类型——描述符类型是否与段寄存器匹配,P位是否为1image-20230802112405142对于CS和SS的选择器,不允许向其传送为0的选择子

代码段执行时的保护:

  1. 执行的代码未超过段界限image-20230802113326549

数据段:

;创建1#描述符,这是一个数据段,对应0~4GB的线性地址空间
mov dword [ebx+0x08],0x0000ffff    ;基地址为0,段界限为0xfffff
mov dword [ebx+0x0c],0x00cf9200    ;粒度为4KB,存储器段描述符 
;这个数据段囊括了整个4G的地址空间,包括代码段,所以虽然代码段无法直接通过代码段的描述符写入,但是可以通过这个数据段写入;创建数据段描述符,实际用做第一个栈段
mov dword [ebx+0x18],0x6c0007ff    ; 基地址0x00006c00,向上扩展,D/B=1
mov dword [ebx+0x1c],0x00409200    ; 界限0x7ff,粒度字节,数据段描述符
;段的扩展方向决定了处理器检查段界限时的检查方向,与栈的推进方向无关
;描述符中的段界限决定了偏移量的变化范围,即栈的容量
;描述符的D/B=1时,使用ESP,反之使用SP
;初始化时将SP/ESP设为段大小,即段界限+1(0x800)
;压栈,高位向低位推进
push dword 0x072e074d ;压入一个双字
; | 07 |  0x07ff
; | 2e |
; | 07 |
; | 4d | <- esp = 0x07fc

向上扩展的数据段,在写入数据之前进行检查:操作数的有效地址(SP/ESP - 压栈值的大小,算的是存入数据的空间) + 操作数的大小(字节)- 1 <= 实际使用的段界限

检查通过后即可写入,写入后SP/ESP指向写入的最后一个栈元素

;出栈
pop dword [0x0b800]
; | 07 |  0x07ff
; | 2e |
; | 07 |
; | 4d | <- esp = 0x07fc

向上扩展的数据段,在弹出数据之前进行检查:操作数的有效地址(SP/ESP) + 操作数的大小(字节)- 1 <= 实际使用的段界限

同样,弹出的数据在存入数据段时也要进行检查:000b8000 + 4 - 1 <= ffff_ffff

内存线性地址回绕特性

image-20230802132448073

向下扩展的段作为栈段:

;创建数据段描述符,实际用作第二个栈段
mov dword [ebx+0x20],0x7c00fffe    ;基地址为0c00007c00,向下扩展,D/B=1
mov dword [ebx+0x24],0x00cf9600    ;段界限为0xffffe,粒度为4KB,数据段描述符 
;初始化使SP/ESP=0

image-20230802132938858

image-20230802133736580

向下扩展的数据段,在写入数据之前进行检查:操作数的有效地址(SP/ESP - 压栈值的大小,算的是存入数据的空间)> 实际使用的段界限

;压栈
;                                |-ffffffff
;                                |--fffffffc <- esp=0-4=fffffffc 负数
;                                |--fffff000 实际使用段界限+1
; 00007c00    | 07 |-------------|-00000000 段基地址
;             | 68 | <- esp

向下扩展的数据段,在弹出数据之前进行检查:操作数的有效地址(SP/ESP)> 实际使用的段界限

xchg al,ah ,交换两操作数内容,可以同时是寄存器,不能同时是内存地址

冒泡排序:

;开始冒泡排序 
mov ecx,pgdt-string-1              ;遍历次数=串长度-1 
@@1:push ecx                           ;32位模式下的loop使用ecx xor bx,bx                          ;32位模式下,偏移量可以是16位,也可以 @@2:                                      ;是后面的32位 mov ax,[string+bx] cmp ah,al                          ;ah中存放的是源字的高字节 jge @@3 xchg al,ah mov [string+bx],ax @@3:inc bx loop @@2 pop ecx loop @@1

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化:Matplotlib详解及实战

1 Matplotlib介绍 Matplotlib是Python中最常用的可视化工具之一,可以非常方便地创建海量类型的2D图表和一些基本的3D图表。 Matplotlib提供了一个套面向绘图对象编程的API接口&#xff0c;能够很轻松地实现各种图像的绘制&#xff0c;并且它可以配合Python GUI工具&#xff08;…

VMware Workstation下载不同的版本

1&#xff1a;访问下载链接 https://customerconnect.vmware.com/cn/downloads/#all_products 2&#xff1a;拉倒下面去选择对应的下载内容 3&#xff1a;先选择大版本 4&#xff1a;大版本选择之后&#xff0c;就可以选择对应的小版本 各位再根据自己的选择进行下载就好了

Spring Boot 单元测试

目录 1.什么是单元测试&#xff1f; 2.单元测试的优点 3.Spring Boot 单元测试使用 3.1 生成单元测试的类 3.2 添加 Spring Boot 框架测试注解&#xff1a;SpringBootTest 3.3 添加单元测试业务逻辑 3.4 注解 Transactional 4. 断言 1.什么是单元测试&#xff1f; 单元…

运维第四次作业

1. 简述静态网页和动态网页的区别。 静态网页和动态网页的区别在于内容的生成方式。静态网页的内容在服务器上预先创建好&#xff0c;并在用户访问时直接传送给浏览器&#xff0c;内容不会改变。而动态网页的内容是在用户访问时才在服务器上生成&#xff0c;可以根据用户的请求…

数据结构——红黑树

文章目录 一.红黑树的定义二.红黑树的插入1.红黑树节点的定义2.红黑树的插入操作3.总结&#xff1a; 三.红黑树与AVL树的比较四.检验手写的红黑树五.源码 一.红黑树的定义 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff…

Typescript+React入门

初识Typescript 出现背景 Typescript&#xff08;以下简称TS&#xff09;实际上就是JavaScriptType&#xff0c;用数据类型的方式来约束了JS的变量定义 在JS的基础上增加了类型支持 在JS中大多数错误都是因为数据类型造成的&#xff0c;所以TS为了规避这个问题加入了类型限制…

【小沐学NLP】在线AI绘画网站(网易云课堂:AI绘画工坊)

文章目录 1、简介1.1 参与方式1.2 模型简介 2、使用费用3、操作步骤3.1 选择模型3.2 输入提示词3.3 调整参数3.4 图片生成 4、测试例子4.1 小狗4.2 蜘蛛侠4.3 人物4.4 龙猫 结语 1、简介 Stable Diffusion是一种强大的图像生成AI&#xff0c;它可以根据输入的文字描述词&#…

从特斯拉FSD v11.4.6,看FSD入华

从特斯拉FSD v11.4.6&#xff0c;看FSD入华 1. 芝加哥城区a. 亮点b. 问题 2. 小镇中心a. 亮点b. 问题 3. FSD入华a. 技术路线b. 场景 4. 参考视频 FSD最近更新了v11.4.6&#xff0c;本文根据2个FSD城区测试视频&#xff0c;一起看一下有哪些亮点和问题。 FSD入华的消息也甚嚣尘…

CentOS7安装Maven详细教程

&#x1f60a; 作者&#xff1a; Eric &#x1f496; 主页&#xff1a; https://blog.csdn.net/weixin_47316183?typeblog &#x1f389; 主题&#xff1a;CentOS7安装Maven详细教程 ⏱️ 创作时间&#xff1a; 2023年08月06日 第一步&#xff1a;上传或下载安装包&#x…

python 输入oracle sql查询语句导出excel表

Author: liukai 2810248865qq.com Date: 2022-08-18 04:28:52 LastEditors: tkhywang 2810248865qq.com LastEditTime: 2023-08-02 18:27:08 FilePath: \PythonProject02\python 连接oracle数据库导出Excel带数据库表头.py Description: 这是默认设置,请设置customMade, 打开ko…

DevOps系列文章之 Docker 安装 NFS 服务器

Docker 安装 NFS 服务器 环境&#xff1a; 192.186.2.105 NFS 服务器 192.168.2.106 Client 客户端 安装 一、服务器端 https://github.com/f-u-z-z-l-e/docker-nfs-server 1、创建目录 mkdir /nfsdata mkdir -p /docker/nfs/2、启动脚本 vim start.sh# 内容 docker run …

Android平台GB28181设备接入端如何降低资源占用和性能消耗

背景 我们在做GB28181设备接入模块的时候&#xff0c;考虑到好多设备性能一般&#xff0c;我们一般的设计思路是&#xff0c;先注册设备到平台侧&#xff0c;平台侧发calalog过来&#xff0c;获取设备信息&#xff0c;然后&#xff0c;设备侧和国标平台侧维持心跳&#xff0c;…