汇编入门
一、基础知识
( 1 )机器语言
机器语言是机器指令的集合。电子计算机的机器指令是一系列二进制数字。计算机将之转换为一系列高低电平脉冲信号来驱动硬件工作的。
(2)汇编语言的产生
我们知道机器只能看懂机器语言,也就是0和1。实际上0和1只是我们规定的数字,机器其实连0和1也看不懂,这里的0和1实际上是指两种不同的电压状态,计算机是用电的,它能理解的就是电压的变化,所以我们通过不同的电压驱动计算机运算,来完成我们所需要的任务。
在早期,人们通过纸带来编程,打孔的地方表示1, 不 打孔的地方表示0,然后将纸带输入计算机中。这种方式不但费时费力,而且不同发现错误。
例如下面的程序:
-
Java 代码
1 |
101110000000000000000011 |
2 |
000001010000000000110000 |
3 |
001011010000000000000101 |
这是8086CPU完成运算s=768+12288-1280的程序,如果这个程序中错误的将一个0写成了1,试想要想发现这个错误是多么的困难。
为了方便人们编写程序,并且避免01代码容易出错的问题,人们发明了汇编语言。
例如:机器指令1000100111011000表示把寄存器BX的内容送到AX中。汇编指令则写成 mov ax,bx 。这样的写法与人类语言接近,便于阅读和记忆。
(3)汇编语言的组成
汇编指令 ( 机器码的助记符,有对应的机器码 ) ;
伪指令 ( 由编译器执行 ) 和 其他符号 ( 由编译器识别 ) 。
(4) 存储器
CPU工作需要指令和数据,指令和数据存储在存储器中。
(5)指令和数据
在内存或者磁盘中存储的都是为二进制信息, 指令和数据由我们设定(走的总线) 。
(6) 存储单元
• 存储器被划分为若干个存储单元,每个存储单元从0开始顺序编号。
• B、KB、MB、GB、TB等单位。
(7)CPU对存储器的读写
我们知道数据和指令是放在内存中的,CPU通过总线对存储器进行访问,但实际上总线是分为三部分的,即地址线,控制线和数据线。地址线表示CPU要对内存中的哪个地址进行操作,所以地址线的条数决定了CPU能够访问的内存范围,因为一根线上最多只能有两种不同的状态即0和1,所以10根地址线能够访问的存储单元的个数就是2^10个。
地址 线仅仅 是送出了要操作的地址,但是并没有声明要进行什么操作,所以控制线就是来决定对存储单元的操作的。所以说控制线的条数决定了CPU能够执行的操作的种类。
数据线是用来在CPU和内存之间进行数据传送的,所以数据线的条数决定了一次最多传送的数据的数量,例如8根数据线一次就能传送8个bit即一个字节。
上图展示了CPU从3号内存单元中读取数据的过程。首先CPU利用数据线送出地址3,然后通过控制线发送读命令,然后内存将结果通过数据线返回给CPU。
(8) 内存地址空间
什么是内存地址空间呢?举例来讲,一个CPU的地址总线宽度为10,那么可以寻址1024个内存单元,这1024个可寻到的内存单元就构成了这个CPU的内存地址空间。当然这里所说的内存并不单单是内存条中的内存,还包括其他各种外设中的RAM和ROM。例如,显卡也有自己的内存,用来存储在显示屏上显示的内容,另外显卡BIOS ROM也被 当做 是内存空间中的一部分,此外还有网卡的BIOS ROM和系统BIOS ROM地址空间等。
因此我们在基于一个计算机硬件系统编程时,必须要知道这个系统中的内存地址空间分配情况。应为当我们想在某类存储器中读写数据的时候,必须知道它的第一个单元地址和最后一个单元地址,才能保证读写操作是在预期的存储器中进行的。比如,我们希望在显示器上输出一段信息,那么必须将这段信息写到显存中,显卡才能将它输出到显示器上,要想向显存中写入数据,必须知道 显存在 地址空间中的地址。
上图展示了8086PC机内存地址空间分配的基本情况。从地址0~9FFFF的内存单元中读取数据,实际上就是在 读取住 随机存储器中的数据;向地址A0000~BFFFF的内存单元中写数据,就是向显示器中写入数据,这些数据 会被显卡 显示到显示器上;我们向C0000~FFFFFF的内存单元中写入数据的操作是无效的,因为这等于改写只读存储器中的内容。
小结:
1、汇编指令时机器指令的助记符,与机器指令一一对应。
2、每一种CPU都有自己的汇编指令集。
3、CPU可以直接使用的信息在存储器中存放。
4、在存储器中指令和数据都是二进制信息。
5、存储单元从0开始顺序编号。
6、一个存储单元可以存储8个bit。
7、B、KB、MB、GB等单位之间的转换。
8、CPU管脚和总线相连。总线的宽度表示CPU不同方面的性能:
(1)地址总线的宽度决定了CPU的寻址能力;
(2)数据总线的宽度决定了CPU与其他器件进行一次数据传送的量;
(3)控制总线宽度决定了CPU对系统中其他器件的控制。
二、寄存器(CPU的工作原理)
CPU由运算器、控制器、寄存器 等器件组成,靠内部总线相连。
内部总线实现CPU内部各器件之间的联系;外部总线实现CPU和主板上其他器件的联系。
在CPU中:
(1)运算器进行信息处理;
(2)寄存器进行信息存储;
(3)控制器控制各种器件进行工作;
(4)内部总线连接各种器件在它们之间进行数据的传送。
1、 通用寄存器
8086有14个寄存器:
AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、CS、ES、PSW。
AX、BX、CX、DX通常用来存放一般性数据,被称为通用寄存器。
16位寄存器所能存储的数据最大值为2^16-1 。
为保证兼容性,8086 CPU的通用寄存器可以分为两个独立的8位寄存器使用。例: AX可分为AH和AL。
2、 字在寄存器中的存储
(1)8086 CPU所有的寄存器是16位,可以存放2个字节(一个字)
(2) 一 字节由8 bit 组成,可以存在8位寄存器中
(3)字(word)是两字节,16位。
3、几条汇编指令
汇编指令对大小写不敏感
4、 物理地址
• 所有的内存单元构成一个一维的线性存储空间。
• CPU访问内存单元时要给出内存单元的唯一地址就是物理地址。
5、16位结构的CPU
• 运算器一次最多可以处理16位数据。
• 寄存器的最大宽度为16位。
• 寄存器和运算器之间的通路是16位。
6、 8086 CPU给出物理地址的方法
• 8086有20位的地址总线,可以传送20位地址,寻址能力为1M;但8086内部为16位结构,只能传送16位的地址。
• 8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。
8086CPU读写内存的步骤:
(1)CPU中的相关部件提供段子和偏移地址这两个16位的地址;
(2)段地址和偏移地址通过内部总线送入到一个称为地址加法器的部件;
(3)地址加法器将两个16位地址合并成一个20位的地址;
(4)地址加法器通过内部总线将20位物理地址 送 送入输入输出地址;
(5)输入输出控制电路将20位物理地址送上地址总线;
(6)20位物理地址被地址总线传送到存储器。
地址加法器工作原理:物理地址=段地址*16+偏移地址。
段地址*16就是数据左移4位(二进制)
一个数据的二进制形式左移N位,相当于该数据乘以2的N次方。一个数据X进制形式左移N位,相当乘以N^X。
7、段地址*16+偏移地址=物理地址
CPU可以通过不同的段地址和偏移地址形成一个相同的物理地址。
8、段的概念
人为定义的,将若干地址连续的内存单元看作一个段。用段地址*16定位段的起始地址(基址),用偏移地址定位段中的内存单元。
一个段的起始地址是16的倍数。偏移地址为16位,寻址能力为64K,所以段的最大长度也是64K
三、寄存器(内存访问)
1、 mov 、add、sub指令
• 有两个操作对象, jmp 只有一个操作对象。
• 使用 汇编金 手指查阅指令
• mov 指令的几种形式
-
Java 代码
1 |
<span style="font-family: 微软雅黑 , 宋体, arial ;"> mov 寄存器,数据; mov ax,8 |
|
2 |
mov 寄存器,寄存器; mov ax,bx |
3 |
mov 寄存器,内存单元; mov ax,[0] |
4 |
mov 内存单元,寄存器; mov [0],ax |
5 |
mov 段寄存器,寄存器; mov ds,ax |
|
6 |
mov 寄存器,段寄存器; mov ax,ds </span> |
• add指令的几种形式
-
Java 代码
1 |
<span style="font-family: 微软雅黑 , 宋体, arial ;">add 通用寄存器,数据 |
|
2 |
add 通用寄存器,通用寄存器 |
3 |
add 通用寄存器,内存单元 |
|
4 |
add 内存单元,寄存器</span> |
• sub指令的几种形式
-
Java 代码
1 |
<span style="font-family: 微软雅黑 , 宋体, arial ;">sub 通用寄存器,数据 |
|
2 |
sub 通用寄存器,通用寄存器 |
3 |
sub 通用寄存器,内存单元 |
|
4 |
sub 内存单元,通用寄存器 </span> |
2、 栈
• 具有特殊的访问方式的存储空间,也是内存空间的一部分,数据 先进后出。
• 有两个基本操作:
o 入 栈 :将一个新的元素放到 栈 顶;
o 出 栈 :从 栈 顶取出一个元素。
• 栈 顶元素最后入 栈 最先出 栈 。
3、8086 CPU提供的 栈 机制
现今的CPU都有 栈 的设计,基于8086CPU编程可以将一段内存当作 栈 来使用。
8086CPU的入 栈 (PUSH)和POP(出 栈 ),以字为单位。
push ax 将寄存器ax中的数据送入 栈
pop ax 从 栈 顶取出数据送入ax
段寄存器SS存放 栈 顶的段地址,寄存器SP存放 栈 顶的偏移地址。任意时刻SS:SP指向 栈 顶元素。push时SP先自减法后写内存,pop先读内存 sp 后自加。
pop之后数据还是存在内存中,push时覆盖。
CS和IP存放当前指令的段地址和偏移地址。
4、 栈 顶越界的问题
• 栈 是空的,则SP指向 栈 底+1的内存。
• 8086 CPU只纪录 栈 顶, 栈 空间由自己控制。 栈 顶越界问题导致溢出漏洞。
• 8086CPU只考虑当前的情况:
o 当前 栈 顶在何处;
o 当前要执行的指令时哪一条。
- 点赞
- 收藏
- 关注作者
评论(0)