第一章:基础知识
- 有哪几类总线?它们各自起到什么作用?
a. 地址总线:寻址,其总线宽度决定寻址范围
b. 数据总线:数据传输,其总线宽度决定一次数据传输量
c. 控制总线:CPU对外部器件的控制线的总称,其总线宽度决定了对外部总线的控制能力. - 宽度为N的地址总线的寻址范围?
a. 2^N 个内存单元,[0, 2^N-1], 一个内存单元是1Byte - 有哪几类存储芯片?有什么区别?
a. 随机存储器RAM: 如内存,可读可写,下电丢失,需带电存储
b. 只读存储器ROM: 如flash/CD,下电不丢失,现在大多ROM器件可写的(早期的ROM只读不可写,或者用非常规的方式写)
c. ROM写性能差但下电不丢失数据,RAM可写可读下电丢失数据 - CPU如何操作各种物理设备?
a. 器件和CPU都会接入总线
b. CPU对器件的操作动作通过控制总线发出
c. 总线和控制线的联系?控制总线是总线的一部分
d. CPU在操作各类器件时,都把它们当作内存地址看待,CPU视角中是若干存储单元组成的逻辑存储器,而该逻辑存储器就是内存地址空间 - 计算题:0~7FFFH是多大的内存空间?如何计算? / A000H ~ FFFFH呢?
a. 32KB
b. (7FFFH-0H+1) = 8000H = 32768B, 32768B / 1024 = 32KB
c. 类似
第二章:寄存器
-
CPU由哪些器件组成?它们分别有什么作用?
a. 运算器ALU: 进行加减乘除逻辑运算
b. 寄存器:负责存储各类不同的数据, ax/cf/si/es/…
c. 控制器: 由指令寄存器IR(InstructionRegister)、程序计数器PC(ProgramCounter)和操作控制器OC(OperationController)组成,IR存储当前正在执行的指令,PC存储是下一条指令地址,OC产生时序信号
d. 内部总线:CPU内部也是有总线的,和外部总线不同,负责CPU内部器件的数据交互 -
有哪些通用寄存器?它们通常会怎么用?
a. ax/bx/cx/dx四种,它们都可以作为tmp变量,但各自又有特殊用途.长度都为16bits,下面介绍各自特殊用途
b. ax: 累加器,在算术运算指令作为结果存放的目的寄存器,也用于各类中断/函数程序的传参/调用结果返回
c. bx: 基址寄存器,配合ds进行内存范围,其中ds是段地址,而bx是偏移地址,常见的:[bx] 等价于 ds:bx
d. cx: 计数寄存器,配合loop指令用于控制循环次数
e. dx: 数据寄存器,io中断操作用于存放IO端口地址,此外该寄存器无特殊的使命
f. 这些寄存器长度均为16位,可以分开用,如ah/al,那么ah和al均为8位长度 -
如下程序计算后ax的结果?
mov ax, 0FFFFh
add al, 1
结果为FF00H,al是作为独立的8位寄存器使用的,做加法进位不会改变cf寄存器(carry flag),不会进位到ah,使用adc指令也不会产生进位.
-
16位机(或者说16位结构CPU)有什么含义?能得到什么信息?
a. 运算器ALU一次最多可以处理16位的数据
b. 寄存器最大宽度为16位
c. 寄存器和运算器之间的通路为16位 -
8086 CPU读写内存的流程
a. CPU相关部件提供两个16位地址,分别是:段地址,偏移地址
b. 段地址和偏移地址通过CPU内部总线送入地址加法器
c. 地址加法器计算20位物理地址=段地址*16+偏移地址
d. 地址加法器通过内部总线将20位物理地址送入输入输出控制电路
e. 输入输出控制电路将20位物理地址送入地址总线
f. 20位物理地址被地址总线传送到存储器
e. 可以得知:段起始地址必然是16倍数,偏移地址为16位,故16位寻址能力是64KB,所以一个段的长度为64KB -
有哪些段寄存器?它们分别的作用是什么?
a. cs(code segment): 配合ip(instruction pointer)来访问指令
b. ds(data segment): 可以通过ds:[立即数] 或 ds:[bx]等进行内存单元数据的访问
c. es(extra segment)
d. ss(stack segment): 配合sp(stack pointer)来访问操作栈, 注意sp可以直接用立即数赋值,而ss不行. -
书第三版p27图2.14,最后一张小图,地址总线送入20000h,数据总线为什么知道只需要传3条指令而不是2条或4条呢?
a. 参考:https://blog.csdn.net/Apelpoo/article/details/51870154 / https://blog.csdn.net/csdn_gddf102384398/article/details/84311183
b. CPU指令集对每条指令(不同寻址方式/不同运算)都规定了不同的机器码。开始时CPU不知道会读取执行什么指令,它将指令地址发到地址总线,然后指令将“逐字节”地通过数据总线传送到CPU中. CPU读取到指令中的操作码(前几个字节)时,就知道了当前指令的长度,也可以知道接下来的CS:IP. -
CS:IP访问指令的流程
a. 从CS:IP指向的内存读指令,读取的指令进入指令缓存器
b. IP=IP+所读取指令的长度,从而指向下一条指令
c. 执行指令,转到(a),重复整个过程
d. 所以如果内存中的一段信息被CPU当作指令执行过,那么其必然被CS:IP指向过 -
刚上电时,内存中也没有数据,那么FFFF0H的指令是从哪里来的?
a. FFFF0H不是内存中的指令,而是ROM中的指令,该指令的任务是负责跳转并执行BIOS程序 -
哪些指令可以修改CS:IP的值? 分别描述这些指令下如何使用?
a. 可以修改cs:ip的值统称为转移指令,如jmp系列,call,ret,iret. mov指令不能修改cs:ip
b. jmp 段地址:偏移地址, 设置cs=段地址,ip=偏移地址
c. jmp 寄存器 (将寄存器的值赋值给ip, cs不变, 相当于mov IP, 寄存器) -
如下指令CPU修改了几次IP,都是什么时候?最后IP值为多少?
mov ax,bx
sub ax, ax
jmp ax
3次,IP=0000H,原题P35检测点2.3
本章习题推荐?
无,不用做
第三章.寄存器(内存访问) --> 通过寄存器访问内存
- 如何通过DS寄存器访问内存单元10005H的字节型数据? 访问内存单元为10010H的字型数据并写入到内存单元为10050H中?
mov bx, 1000h
mov ds, bx
mov al, ds:[5] ; 注: masm下,直接写成mov al, [5], masm会直接将5当作立即数赋值给al,出现错误; 根因在<5.4节,Debug和汇编编译器masm对指令的不同处理>一章会解释
mov ax, ds:[10h]
mov ds:[50h], ax ; 注: masm下, 写操作时需要写成ds:[50H],否则masm中编译会出现Immediate mode illegal,masm将[50h]看成立即数
- mov/add/sub指令格式
mov reg, data ; eg. mov ax, 8; mov sp, 2h
mov reg, reg ; eg. mov ax, bx
mov reg, mem ; eg. mov ax, ds:[0]
mov mem, reg ; eg. mov ds:[0], ax
mov segreg, reg ; eg. mov ds, ax
mov reg, segreg ; eg. mov ax, ds
mov mem, segreg ; eg. mov ds:[0], cs
mov segreg, mem ; eg. mov ds, ds:[0]
而add/sub,不能直接对段寄存器进行操作
-
push ax执行流程? push al呢?
a. SP=SP-2 ,SS:SP指向当前栈顶前一个单元
b. ax送入SS:SP指向的内存单元处
c. 8086中,入栈时,栈顶从高地址向低地址增长. 实际上现代CPU的栈更新都是如此,堆则是从低到高.
d. push al是非法的操作
f. push reg/push segreg/push mem -
pop ax执行流程?
a. 将SS:SP内存单元处的数据送入ax
b. SP=SP+2
c. pop reg/pop segreg/push mem -
栈顶超界问题如何避免?
a. 8086CPU没有有效的机制避免栈超界问题,只记录栈顶
b. 首先要确保开辟的栈大小空间足够,其次要可以自己编写错误处理逻辑 -
使用栈push/pop和mov内存单元的区别?
a. push/pop由两个汇编指令组成的,而mov只有一个; 实际执行需要的cycle是push快还是mov快是需要确认的
b. SP范围是[0,FFFFH],故栈的大小是64M.
c. 栈为空时, SP=FFFFH+1=0H; 入栈时,SP=SP-2=FFFEH -
实验2中阐述了一个知识点:使用DEBUG.exe,用t单步,mov ss,ax之后,会紧接着执行下一条指令.且不单是mov ss,ax,所有修改栈段寄存器ss的指令都会有相同的情况,这个是什么原因?
a. 从此知识点可知,最好以mov ss,xx; mov sp, yy这个顺序编写;而不是反着,因为mov ss,xx会导致紧接着执行下一条指令.
b. 这样设计的原因是因为:SS:SP联合指向栈顶,而对它们的设置应该连续完成。如果在执行完设置SS的指令后,CPU相应中断,引发中断过程,要在栈中压入标志寄存器、CS和IP的值。而SS改变,SP并未改变,SS:SP指向的不是正确的栈顶,将引发错误。所以CPU在执行完设置SS的指令后,并不响应中断。这给连续设置SS、SP的指向正确的栈顶提供了一个时机。
c. 根据b,就可以知道当设置ss,sp时,系统会关中断响应,然后设置完成后再开启
d. 所以,必须先设置ss,再设置sp,必须连在一起写,以防止难以排查的问题
f. 不连在一起写或反过来写,也可以通过编译,但不要这么做.
本章习题推荐?
检测点3.1 (2) / 检测点3.2(1)(2)
第4章
- DOS中EXE程序加载过程
a. 找到起始地址为SA:0000(即起始地址的偏移地址为0)且容量足够的空闲内存区
b. 在这段内存区的前256B中,创建一个称为程序段前缀(PSP)的数据区,DOS利用PSP来和被加载程序进行通信
c. 从这段内存区的256B开始(刚好在PSP后面),将程序装入,程序的地址被设为SA+10H:0;
d. 将该内存区的段地址存入ds中,初始化其他相关寄存器后,设置CS:IP指向程序入口
e. 使用DEBUG.EXE,将程序加载入内存后,cx中存放程序长度,ds区就是PSP区开始; 因为PSP区是256B,故可以看到CS和DS差10H
f. PSP区与程序区物理地址连续,但有不同段地址.空闲内存区:SA(Start Address):0 ; PSP区: SA:0 ; 程序区: (SA+10H):0
g. PSP区的头两个字节是CD 20
DEBUG工具使用
- R:查看/修改CPU寄存器, 如 r ip,就会进入交互式修改寄存器ip
- D:查看内存,如d 1000:0 就可以查看1000:0开始,默认为80H个字节内存中的数据, 或者可用 d 1000:0 f查看1000:0开始,f个字节的数据, 或者可用 d cs:0 看到cs的内容
- E:修改内存,如e 1000:0 0 1 2 3 4 5 6 7 8 9,修改1000:0开始,10个字节的内存单元数据为0~9
- U:将内存中数据显示成汇编指令, 如u 1000:0 1e ,从1000:0开始,范围是1e的内存单元数据以汇编指令形式显示
- T:单步执行一条汇编
- A:在内存中写入一条机器指令,如a 1000:0,进入交互式,输入汇编指令,就可以把1000:0开始的内存单元修改成汇编指令对应的机器指令
- P:执行到下一条指令(如果某条指令是循环,P就可以把循环执行完跳转到下一条指令,如果是死循环则就会卡死); 另外,int 21指令要用P执行
- G: 可以一直执行直到某个IP,如g 0012, 就会向下执行到当前CS:0012的位置