汇编学习
cpu与存储器

cpu对外部器件读写数据工作原理,不同的机器码可以对应数据或者指令,分出了三种总线:
cpu由地址总线发出寻址数据
地址宽度由其并联的导线数决定,一个导线有0,1两种状态,宽度决定了其寻址数,为2^ncpu经控制总线发出指令,对所在地址进行操作
控制总线的宽度决定了cpu对外部器件控制的能力内存与cpu经过数据总线来传递数据
数据总线并联的导线数量决定了一次传输的位
存储器芯片
- RAM:可读可写,需要通电
- ROM:只读不可写,断电后不会丢失数据,可以存放bios
这些存储器与cpu通过总线相连,但是cpu都把他们当做内存单元
cpu会以一定逻辑对地址进行分类
当我们需要对一个计算机硬件系统进行编程时,必须要了解起始地址和结束地址,以及存储器地址分配的结构
cpu内部
一个典型的cpu由运算器、控制器、寄存器等器件构成,他们之间通过内部总线连接
8086cpu寄存器
通用寄存器(8个):
- AX(累加器寄存器)
- BX(基地址寄存器)
- CX(计数器寄存器)
- DX(数据寄存器)
- SP(堆栈指针寄存器)
- BP(基指针寄存器)
- SI(源变址寄存器)
- DI(目的变址寄存器)
段寄存器(4个):
- CS(代码段寄存器)
- DS(数据段寄存器)
- SS(堆栈段寄存器)
- ES(附加段寄存器)
控制寄存器(2个):
- IP(指令指针寄存器)
- FLAG(标志寄存器)
通用寄存器
AX、BX、CX、DX用来存放一般性数据,称为通用寄存器
8086由于需要对上代8位寄存器的兼容,可以把一个16进制的寄存器分为两个8进制寄存器
高八位位AH寄存器,低八位为AL寄存器
字节与字
一个字节有八位,一个子有两个字节16位
一些汇编指令
mov a,b 相当于给变量赋值操作,b的值赋值给a
add a,b 相当于相加操作,相加后的结果赋值给a
- 当一个寄存器存储的数据高于十六位时,为丢弃最高位的数据吗,一个十六进制数据占四个bit,所以八bit寄存器只能存放两个十六进制数据
8086的寻址办法
8086有20为的地址总线,意味着总线的寻址能力达到1mb。
而8086是16位结构,意味着8086内部只能一次性处理、传输、暂时存储的地址为16位,表现出的寻址能力仅为64kb
所以在8086内部有一种形成20位物理地址的方法,结构如下
地址加法器采用:物理地址=段地址×16+偏移地址 的方法形成物理地址,加法器的工作原理如图
还是那个算法,一个十六进制数据占4为,一个16+4=20位存储器能表示5个16进制数据,
意思就是把偏移地址加入到低位
总的来说,8086cpu在用20位地址总线来访问地址时,会用 基础地址+偏移地址+物理地址 的方法寻址
超级形象的例子:
当然了,不能强行将两个16进制构造出32位数据,必然会丢弃一些信息,所以,不同的两个16进制段地址 和 偏移地址 可能指向相同的20进制 物理地址
引入段寄存器,非常关键
段寄存器
CS:代码段寄存器
IP:指令指针寄存器
CS内容当做段地址,IP内容当做偏移地址,合成物理地址,读取存储器内容,当做指令执行
在CS和IP寄存器的驱动下,cpu执行指令的操作

获得mov ax,0123H的指令

读取下一条指令时,IP(偏移地址+3,指向初始位置,如果指令长度为2则会自动+2)
以此类推,总结是这样的
别看CS和IP是寄存器,但是他们不能通过mov指令来修改(cpu没有提供这样的功能)
那么问题来了,如何修改呢?
引入jmp指令
jmp指令
修改CS、IP内容
仅修改IP的内容,可用 "jmp 寄存器名称的方式"
内存中的字存储
在内存中一个地址只能存放一个8位(1字节)数据,但是cpu寄存器是存放16(2字节)位数据的,当我们的寄存器访问内存时,会将低八位和高八位两个内存地址的数据进行传输
数据段
可以根据需要将一段内存单元定义为数据段,在寄存器DS中存放数据段的段地址
在意这样的形式对数据段的内容进行读取
在8086cpu中可以通过mov直接对内存单元进行访问,就是说x86架构中CPU可以直接对内存进行操作
栈
栈是一种具有特殊的访问方式的存储空间
最后进入这个空间的数据,最先出去
准确的理解何为栈,栈顶是变化的,总有一个指针会指向栈顶
cpu提供的栈机制
有两个寄存器对栈内存进行指示--SS和SP,任意时刻,SS:SP指向栈顶元素
入栈时,栈顶从高地址向低地址方向延伸
当入栈被执行时,首先减去数据占用的内存空间,然后指向新的栈顶,最后存储低位和高位数据
栈顶超界问题
8086cpu不能处理栈顶超上界和下界的问题
push和pop指令
push和pop不仅可以对寄存器操作还可以对内存单元操作,以字为单位(两个字节为一字,也就是两个内存地址)
执行push指令时,先将SP的值-2
再进行数据写入,高位写入高地址,低位写入低地址
执行pop命令时,先从SS:SP进行读取值,再进行SP=SP+2