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