第三章笔记《操作系统真相还原》

  • section
  • vstart
  • CPU的工作原理
  • 通用寄存器介绍
  • 实模式下CPU内存寻址方式
  • 实模式下的ret
  • 实模式下的Call
  • 实模式下的jmp
  • Eflag寄存器标志位
  • CPU如何与外设通信--IO接口
  • A32体系的in, out指令

section

关键字section并没有对程序中的地址产生任何影响,即在默认的情况下,有没有section是一样的,section相当于整个文件的顺延,仅仅是逻辑上让开发人员梳理程序之用。

vstart

为section指定一个虚拟的起始地址,根据此地址,在文件是找不到相关数据的,他被用来计算该section内的所有内存引用地dec。整个虚拟地址与x86CPU中开启分页后的虚拟地址是两码事。

CPU的工作原理

控制单元要取下一条待运行的指令,该指令的地址在程序计数器PC中,在x86CPU上,程序计数器CS:IP。于是读取ip寄存器后,将该地址送入地址总线,CPU根据此地址便得到了指令,并将其存入指令寄存器IR中,这时候轮到指令译码器上场了,它根据指令格式指令寄存器中的指令,先确定操作码是什么,再检查操作数类型,若在内存中,就将相应操作数从内存中取回放入自己的存储单元,若操作数是在寄存器中就直接用了,免了取操作数的过程。操作码有了,操作数有了,操作控制器给运算单元下令,开始执行指令。ip寄存器被加上当前指令的大小,于是ip又指向了下一条指令的地址。

通用寄存器介绍

寄存器 助记名称 功能描述
ax 累加器accumulator 使用频度最高,常用于算术运算、逻辑运算、保存与外设输入输出数据
bx 基址寄存器base 常用于存储内存地址,用此地址作为基址,用来遍历一片内存区域
cx 计数器 counter 用于计数,所以常用于循环指令中的循环次数
dx 数据寄存器 data 可用于存放数据,通常用于保存外设控制器的端口号地址
si 源变址寄存器source index 常用于字符串操作中的数据源地址,即被传送的数据在哪里。通常需要与其他指令配合使用,如批量数据传送指令族 mov[bwd]
di 目的变址寄存器 destination index 和si一样,常用于字符串操作。但di是用于数据的目的地址,即数据被传送到哪里
sp 栈指针寄存器stack pointer 其段基址是SS用于指向栈顶。随着栈中数据的进出,push与pop这两个对栈操作的指令会修改sp的值
bp 基址指针寄存器base point 访问栈的两种方式,一种是用push和pop指令操作栈,sp指针的值会自动更新,但我们只能获取栈顶sp指向的数据。很多时候,我们需要读写在栈底与栈顶之间的数据,处理器为了让开发人员方便控制栈中的数据,还提供了把栈当成数据段来访问的方式,即提供寄存器bp,所以bp默认的段寄存器是SS,可通过SS:bp的方式把栈中的数据当成普通的数据段来访问

实模式下CPU内存寻址方式

从大方向上看,寻址方式可分为三类:

  • 寄存器寻址
  • 立即数寻址
  • 内存寻址
    内存寻址又分为:
  • 直接寻址
  • 基址寻址
  • 变址寻址
  • 基址变址寻址
寻址说明:
  • 寄存器寻址
    “数”在寄存器中,直接从寄存器中获取数据。下面三条指令都是寄存器,其中前两条,因为源操作数是立即数,所以也是立即数寻址。
mov ax, 0x10
mov dx, 0x9
mul dx
  • 立即数寻址
    立即数就是常数。指令有操作码与操作数组成,如果立即数存在与指令中,凸显了立即就可用,为立即数寻址
mov ax,0x18    //立即数寻址
mov ds,ax      //寄存器寻址
  • 内存寻址
    操作数在内存中的寻址方式成为内存寻址。
    • 直接寻址
      就是直接在操作数中给出的数字作为内存地址,通过中括号的形式告诉CPU,取此地址作为操作数。
mov ax, [0x1234]
mov ax, [fs:0x5678]
  • 基址寻址
    操作数中使用bx寄存器或bp寄存器作为地址的起始,地址的变化以它为基础。用寄存器作为内存寻址。
mov [bx], 0x1234 //内存基址寻址,立即数寻址
  • 变址寻址
    变址寻址起始和基址寻址类似,只是寄存器由bx,bp换成了si和di。si是指源索引寄存器(source index),di是指目的索引寄存器(destination index)。两个寄存器的默认段寄存器也是ds。
mov [di], ax        //将寄存器ax的值放入ds:di指向的内存 基于ds基址加上di变址指向的内存
mov [si+0x1234], ax    //变址中还可以加上个偏移量

变址寻址主要用于字符搬运方面的指令,这两个寄存器在很多指令中都要成对使用,如movsb,movsw,movsd

  • 基址变址寻址
    即基址寄存器bx或bp加一个变址寄存器si或di。
mov [bx + di], ax
mov [bx + si], ax

实模式下的ret

凡是调用call指令,会把返回地址压入栈中。然而保存的这个地址并不会给call指令使用,call指令不会自动回来。返回地址是给ret,retf使用的。

  • ret : 在栈顶弹出2字节的内容来替换IP寄存器,ret指令不管里面的内容如何,只负责弹出栈顶的内容并为IP寄存器赋值。
  • retf: 从栈顶弹出4字节的内容,栈顶处的2字节来替换IP寄存器,另外的2字节来替换CS寄存器。

实模式下的Call

  • 16位实模式的相对近调用
    “近”是指同一段内,段基址不会变,给出段内偏移地址就可以了。
    “相对”是指在同一个代码段中,只要给出目标函数的相对地址即可。
    指令格式:call near 立即数地址
call near near_proc   //相对近调用
jmp $
addr add 4
near_proc:
  mov ax, 0x1234
  ret
  • 16位实模式间接绝对近调用
    “间接”是指目标函数地址没有直接给出来。
    “绝对”是指目标函数的地址是绝对地址
    格式:
call 寄存器寻址
call 内存寻址
mov ax, near_proc
call ax
jmp $
addr dd 4
near_proc:
  mov ax, 0x1234
  ret
  • 16位实模式直接绝对远调用
    “直接”是指操作数直接在指令中给出,是立即数。不需要经过寄存器或内存。
    “远”是指跨段,目标函数与当前指令不在一个段中。
    格式:
    call far 段基址(立即数):段内偏移地址(立即数)
    如:
section call_test vstart=0x900
call 0: far_proc
jmp $
far_proc:
  mov ax, 0x1234
  retf
  • 16位实模式间接绝对远调用
    “间接”,值目标地址不是立即数,而是在内存或寄存器中。
    格式
    call far 内存寻址
section call_test vstart=0x900
call far [addr]
jmp $
addr dw far_proc, 0
far_proc:
    mov ax, 0x1234
    retf

实模式下的jmp

无条件跳转,jmp通过改变段寄存器CS与IP的值来实现程序跳转的。

  • 16位实模式相对短转移
    “相对”,意味着操作数是个相对的增量。跳转后的地址是目标地址减去当前地址,所得的差再减去jmp指令的2字节,最终的结果就是操作数。操作数的返回在-128-127
    “短转移”,意味着只在段内转移,不需要跨段,所以只需要给出偏移地址就够了。
    格式:
    jmp short 立即数地址
section call_test vstart=0x900
jmp short start
times 127 db 0
start:
    mov ax, 0x1234
    jmp $
  • 16位实模式相对近转移
    相对近转移与相对短转移相比,操作数的范围由8位宽度变为了16位宽度,操作数依然是相对增量。操作数范围是-32768-32767
    格式
    jmp near 立即数地址
section call_test vstart=0x900
jmp short start
times 128 db 0
start:
    mov ax, 0x1234
    jmp $
  • 16位实模式间接绝对近转移
    格式:
jmp near 寄存器寻址 
jmp near 内存寻址
section call_test vstart=0x900
mov ax, start
jmp near ax
times 128 db 0
start:
    mov ax, 0x1234
    jmp $
  • 16位实模式直接绝对远转移
    格式:
jmp 段基址:段偏移地址
section call_test vstart=0x900
jmp 0: start
times 128 db 0
start:
    mov ax, 0x1234
    jmp $
  • 16位实模式间接绝对远转移
    需要在内存中取四个字节,前两个字节是段内偏移地址,后两个字节是段基址。
    格式:
jmp far 内存寻址
section call_test vstart=0x900
jmp far [addr]
times 128 db 0
addr dw start, 0
start:
    mov ax, 0x1234
    jmp $

Eflag寄存器标志位

第三章笔记《操作系统真相还原》_第1张图片
Eflag标志位.png
  • CF Carray Flag:,CF为1,表示进位或借位
  • PF Parity Flag:奇偶位,用来标记低八位中1的个数
  • AF Auxiliary carry Flag:辅助进位标志,用来记录运算结果低四位的进借位情况。
  • ZF Zero Flag:零标志位。若计算结果位0,此标志为1
  • SF Sign Flag:符号标志位。运算结果为负,则SF位为1
  • TF Trap Flag:陷阱标志位。TF为1,CPU进入单步运行模式。debug单步调试时,原理是让TF置一
  • IF Interrupt Flag:中断标志位。IF为1,表示中断开启,CPU可以响应外部可屏蔽中断。
  • DF Direction Flag:方向标志位。用于字符串操作指令中,当DF为1时,指令中的操作数地址会自动减少一个单位,当DF为0时,指令中的操作数地址会自动增加一个单位。其中提到的这个单位的大小,取决于用什么指令。
  • OF Overflow Flag:溢出标志位。表示计算结果是否超过了数据类型可表示的大小。
  • IOPL Input Output Privilege Level:用于特权级概念的CPU。占用两位表示4中特权级
  • NT Nest Task:任务嵌套标志。8088支持多任务,一个任务就是一个进程。一个任务中又嵌套调用了另一个任务时,此NT为1
  • RF Resume Flag:恢复标志位。该标志位用于程序调试,指示是否接受调试故障,它需要和调试寄存器一起使用
  • VM Virtual 8086 Model:虚拟8086模式,这是实模式向保护模式过渡时的产物。此位为1,可以在保护模式下运行实模式的程序。在保护模式下运行实模式程序,都要为其虚拟一个实模式环境,故称为虚拟模式。
  • AC Alignment Check:对齐检查。程序中的数据或指令其内存地址是否是偶数,是否是16,32的整数倍,没有余数。
  • VIF Virtual Interrupt Flag:虚拟中断标志位,虚拟模式下的中断标志。
  • VIP Virtual Interrupt Pending:虚拟中断挂起标志位。在多任务的情况下,为操作系统提供虚拟中断挂起信息。
  • ID Identification:识别标志位。系统经常需要判断CPU型号,若ID为1,表示支持CPU id 指令
  • ``

CPU如何与外设通信--IO接口

IO接口的功能:

  1. 设置数据缓冲,解决CPU与外设的速度不匹配。
  2. 设置信号电平转换电路。CPU是TTL电平,而外设大部分是机电设备。
  3. 设置数据格式转换。外设输出的信息可能是数字信息,模拟信号,而CPU只能处理数字信号
  4. 设置时序控制电路来同步CPU和外部设备。
  5. 提供地址译码
  • 同一时间,CPU只能与一个IO接口通信,仲裁IO接口的竞争,连接各种内部总线,这就是输入输出控制中心(I/O control iub ICH),也就是南桥芯片
  • 南桥芯片一般用来来见pci,pci-express,AGP等低速设备,北桥用于连接高速设备如内存


    第三章笔记《操作系统真相还原》_第2张图片

IA32体系的in, out指令

  • in: 从端口中读取数据.

    • in al, dx
    • in ax, dx
      其中al,ax用与存储由端口获取的数据,可变。dx代表端口号
  • out: 向端口写入数据

    • out dx, ax
    • out dx al
    • out 立即数, al
    • out 立即数, ax
      out指令的目的操作数是端口号。

你可能感兴趣的:(第三章笔记《操作系统真相还原》)