目录
cpu内部概述
像控制总线,地址总线,数据总线相对CPU内部来说是外部总线。而cpu内部总线是由运算器,控制器和寄存器等器件构成。
对于这些器件:
运算器:进行信息处理
控制器:控制各种器件来工作
寄存器:进行信息存储
内部总线:连接各种器件,进行彼此的数据传送
关于寄存器
以8086cpu为例。它的14个寄存器都是16位的。不同的cpu寄存器个数和结构都是不相同的。
16位结构(16位机、字长16位):
运算器一次最多处理16位数据;
寄存器最大宽度16位;
寄存器和运算器之间通路16位。
即,一次性处理、传输、暂时存储的信息最大长度为16位。
这些寄存器,像CS、IP,SS、SP,BP等都是存放特定地址的。而AX、BX、CX、DX这些单纯存放一般性数据的我们称之为通用寄存器。
出于兼容性考虑,8086cpu一次性可处理两种尺寸类型的数据:
字节:byte ,占8bit ,可存8位寄存器中
字: word ,占2byte,两个byte从位置上称为高位字节和低位字节。
字单元,存放一个字型数据(16位),由两个地址连续的内存单元组成(由低到高)。
我们将起始地址为N的字单元简称为N地址字单元。
通用寄存器
为了保证兼容,16位的通用寄存器可以分为两个独立使用的8位寄存器来使用。
像AX可分为AH和AL。当我们单独使用8位寄存器,来使用一些汇编指令时,我们会针对8位寄存器的特性来操作。例如16位寄存器中的后8位寄存器数据,它的最高位一旦发生进位就会丢失,不要想当然觉得前8位的寄存器兜底。(想进位你就老老实实用16位寄存器表示)
指令的两个操作对象位数要一致
mov ax,bx add ax,bx add ax,20000
√correct
mov ax,bl #8位传送到16位 mov al ,20000 #al作为8位寄存器 ,最大存储255 add al,100H #将高于8位的数据加到8位寄存器,数据丢失
Xmistake
物理地址传输
传输方式
还是以8086cpu为例。它的寻址能力是1MB,即可以传送20位地址,有20位地址总线。但它又是16位结构。这是怎么完成的?
方法是:用两个16位地址合成表示一个20位物理地址。
eg:8086cpu读写内存时
1.cpu提供两个16位地址,一个段地址,一个偏移地址;
2.两个地址通过内部总线送入地址加法器,将 16*2合成为20;
3.将20位物理地址送入 输入输出控制电路;
4.输入输出控制电路将20位物理地址 送入 地址总线,
通过地址总线传送到存储器。
地址加法器方法:20位物理地址 = 段地址 * 16 + 偏移地址(乘16即左移一位)
由于偏移地址是16位寄存器传送,所以它的范围是2^16,即0-FFFFH。
偏移地址的灵活性,决定了CPU可以用不同的段地址+偏移地址表示同一 物理地址。
关于代码段地址CS
8086cpu有4个段寄存器 来存放段地址: CS、DS、SS、ES。
CS作为代码段寄存器,对应的IP是指令指针寄存器。
存放指令执行的过程如下:
1.从cs:ip指向的内存单元读取指令,读取的指令进入指令缓冲器;
2.IP=IP + 所读取指令的长度, 从而指向下一条指令;
3.执行指令。转到步骤(1),重复
对段地址修改的方法:
CPU中,程序员能用指令读写的部件只有寄存器。(可通过改变寄存器内容实现对CPU的控制)
mov作为传送指令不能直接修改段寄存器。可以用jmp 段地址:偏移地址 完成修改。
若仅修改IP的内容,可用 jmp +寄存器 直接完成。
关于数据段地址DS
DS寄存器用来存放要访问数据的段地址
eg: mov al,[0]
这是传送指令mov 将 内存单元地址 的内容 传送到 寄存器中。
[...]表示内存单元的偏移地址,而内存单元的段地址则在数据段寄存器DS中被自动取出。
这就涉及到了对数据段寄存器DS的修改。上文可知不可用mov直接完成修改,
我们的方法是,用一个寄存器进行中转,先将数据送入一个一般寄存器,如bx,再将bx中的内容送入ds。
eg:
mov bx,1000H
mov ds,bx
mov [0],al
关于栈段SS
栈的机制不再赘述。
栈顶段地址存放在SS中,偏移地址存放在SP中。
任意时刻,SS:SP 指向栈顶元素。
两个重要指令:PUSH和POP
push ax:
1.SP = SP-2 ,SS:SP 指向当前栈顶前面(2个单位)的单元,以该单元为新栈顶
2.将ax中的内容送入SS:SP指向的内存单元处,SS:SP指向新栈顶。(送入数据)
pop ax
1.将SS:SP 指向的内存单元处数据送入ax中 (读取数据)
2.SP=SP+2,SS:SP 指向当前栈顶下面的单元,以该单元为新栈顶
当然,当栈空使用pop,栈顶使用push时,都会出现越界问题。从而覆盖原数据。
段
1.代码段 CS(code segment):
运行CS:IP 指向的内存单元中的内容
2.数据段 DS(data segment):
存放/读取 一些数据到指定的内存单元
3.栈段 SS (stack segment):
提前定义好栈段,将一连串内存当作栈空间来访问。
段是根据需求提前定义好的,而不是必然有一段空间供我们去使用。
所以一段空间既可以是代码段,也可以是栈段,又可以是数据段。
常用指令
传送指令:mov
mov 寄存器,数据 如:mov ax 8
mov 寄存器,寄存器 如:mov ax,bx
mov 寄存器,内存单元 如:mov ax,[0]
mov 内存单元,寄存器 如:mov [0],ax
mov 段寄存器,寄存器 如:mov ds,ax
add:
add 寄存器,数据 如:add ax,8
add 寄存器,寄存器 如: add ax,bx
add 寄存器,内存单元 如:add ax,[0]
add 内存单元 , 寄存器 如:add [0] ,ax
sub:
sub 寄存器,数据 如: sub ax,9
sub 寄存器,寄存器 如:sub ax,bx
sub 寄存器,内存单元 如:sub ax,[0]
sub 内存单元,寄存器 如:sub [0],ax
栈操作指令:
push 寄存器
push 段寄存器
push 内存单元
POP同理。
——————————————————————————————————————————
dosbox
dosbox汇编环境下的机器指令和汇编指令。
Debug:实模式程序调试工具,可以查看CPU各种寄存器中的内容、内存的情况和机器码级跟踪程序的运行。
功能:
-R | 查看、改变CPU寄存器的内容 | -r -r 寄存器名(可修改) |
-D | 查看内存中的内容 | -d 段地址:偏移地址 (16*8个内容) -d address + 数量-1 (从0开始指定数目) |
-E | 改写内存中的内容 | -e 1000:0010 |
-U | 将内存中机器指令翻译成汇编指令 | -u address |
-T | 执行一条机器指令 | 直接执行 cs:ip 处 的指令(自动位移) |
-A | 以汇编指令格式写入内存一条机器指令 | -a address 汇编指令 |