本文已参与「新人创作礼」活动,一起开启掘金创作之路
机器语言
机器语言是机器指令的集合
机器指令展开来讲就是一台机器可以正确执行的命令。
指令:01010000(PUSH AX)
电平脉冲:
汇编语言的产生
汇编语言的主体是汇编指令
汇编指令和机器指令的差别在于指令的表示方法上。汇编指令是机器指令便于记忆的书写格式。
汇编语言是机器指令的助记符。
机器指令:100 010 011 101 110 00
操作: 寄存器BX的内容送到AX中
汇编指令: MOV AX, BX
寄存器:简单的讲就是CPU中可以存储数据的器件,一个CPU中有多个寄存器。
AX是其中一个寄存器的代号
BX是其中一个寄存器的代号
汇编语言的组成
汇编语言由三类组成
- 汇编指令(机器码的助记符)
- 伪指令 (由编译器执行)
- 其他符号 (由编译器识别)
汇编语言的核心是汇编指令,它决定了汇编语言的特性。
存储器
cpu 是计算机的核心部件,它控制整个计算机的运行并进行运算,
要想让一个cpu工作,就必须向它提供指令和数据。
- 指令和数据在存储器中存放,也就是平时所说的内存。
- 在一台PC机中存在的作用仅次于cpu
- 离开了内存,性能再好的cpu也无法工作。
- 磁盘不同于内存,磁盘上的数据或程序,如果不读到内存中,就无法被cpu使用
指令和数据
指令和数据是应用上的概念。
在内存或磁盘上,指令和数据没有任何区别,都是二进制信息。
二进制信息 :
1000 1001 1101 1000 ->89D8H(数据)
->MOV AX, BX(程序)
存储单元
存储器被划分为若干个存储单元,每个存储单元从0开始顺序编号
例如: 一个存储器有128个存储单元, 编号从0~127
对于大容量的存储器一般还用以下单位来计量容量(以下用B来表示Byte):
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
磁盘的容量单位同内存的一样,实际上以上单位是微机中常用的计量单位。
cpu对于存储器的读写
cpu要想进行数据的读写,必须和外部器件(标准的说法是芯片)
进行三类信息的交互:
- 存储单元的地址(地址信息)
- 器件的选择,读或写命令(控制信息)
- 读或写的数据(数据信息)
cpu对存储器的读写
在计算机中专门有连接cpu和其他芯片的导线,通常称为总线。
物理上: 一跟跟导线的集合;
逻辑上划分为:
- 地址总线
- 数据总线
- 控制总线
总线在逻辑上划分的图示:
对于8086cpu,下面的机器码能够完成从3号单元读数据
机器码: 1010000 00000 11 00000000
地址总线
cpu是通过地址总线来指定存储单元的
地址总线上能传送多少个不同的信息,cpu就可以对多个存储单元进行寻址。
一个cpu有N根地址总线,则可以说这个cpu的地址总线的宽度为N
这样的cpu 最多可以寻找2的N次方个内存单元。
数据总线
cpu与内存或其他器件之间的数据传送是通过数据总线来进行的
数据总线的宽度决定了cpu和外界的数据传书速度。
控制总线
cpu对外部器件的控制是通过控制总线来进行的。在这里控制总线是个总称,控制总线是一些不同控制线的集合。
有多少根控制总线,就意味着cpu提供了对外部器件的多少种控制。
所以,控制总线的宽度决定了cpu对外部器件的控制能力。
前面所讲的内存读或写命令是由几根控制线综合发出的:
- 其中有一根名为读信号输出控制线负责由cpu向外传送读信号,cpu向该控制线上输出低电平表示将要读取数据;
- 有一根名为写信号输出控制线负责由cpu向外传送写信号。
内存地址和空间
一个cpu的地址线宽度为10, 那么可以寻址1024个内存单元,这个1024个内存单元就构成了这个cpu的内存地址空间。
主板
每一台PC机中,都有一个主板,主板上有核心器件和一些主要器件。
这些器件通过总线(地址总线,数据总线,控制总线)相连。
接口卡
计算机系统中,所有可用程序控制其工作的设备,必须受到CPU的控制
CPU对外部设备不能直接控制,如显示器,音箱,,打印机等。直接控制这些设备进行工作的是插在扩展插槽上的接口卡。
各类存储器芯片
从读写属性上来看分为两大类:
随机存储器(RAM)和只读存储器(ROM)
从功能和链接上分类:
- 随机存储器RAM
- 装有BIOS的ROM
- 接口卡上的RAM
装有BIOS的ROM
BIOS: Basic Input/Output System, 基于输入输出系统。
BIOS是由主板和各类接口卡(如:显卡, 网卡等)厂商提供的软件系统,可以通过它利用该硬件设备进行最基本的输入输出。在主板和某些接口卡上插有存储相应BIOS的ROM。
内存地址空间
- 都和CPU的总线相连
- CPU对它们进行读或写的时候都通过控制线发出内存对读写命令。
寄存器
cpu概述
一个典型的CPU由运算器,控制器,寄存器等器件组成,这些器件靠内部总线相连。
区别:
- 内部总线实现CPU内部各个器件之间的联系。
- 外部总线实现CPU和主板上其他器件的联系。
通用寄存器
8086CPU所有的寄存器都是16位的,可以存放两个字节。
AX,BX,CX,DX通常用来存放一般性数据被称为通用寄存器。
AX为例,看寄存器的逻辑结构。
数据:18
二进制: 10010
在寄存器AX中的存储:
8086上一代CPU中的寄存器都是8位的;未来保证兼容性,
这四个寄存器都可以分为两个独立的8位寄存器使用。
- AX可以分为AH和AL
- BX可以分为BH和BL
- CX可以分为CH和CL
- DX可以分为DH和DL
8086CPU的8位寄存器存储逻辑
以AX位例,8086CPU的16位寄存器分为两个8位寄存器的情况:(为了向下兼容)
| 寄存器 | 寄存器中的数据 | 所表示的值 |
|---|---|---|
| AX | 0100111000100000 | 20000(4E20H) |
| AH | 01001110 | 78(4EH) |
| AL | 00100000 | 32(20H) |
字在寄存器中的存储
一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然
就存在这个寄存器的高8位寄存器和低8位寄存器中
(每四个二进制的位可以用,一个十六进制来表示)
几条汇编指令
汇编指令不区分大小写
| 汇编指令 | 控制CPU完成的操作 | 用高级语言的语法描述 |
|---|---|---|
| mov ax, 18 | 将8送到AX | AX = 18 |
| mov ah, 78 | 将78送到AH | AH = 78 |
| add ax, 8 | 将寄存器AX中的数值加上8 | AX = AX+8 |
| mov ax,bx | 将寄存器BX中的数据送入寄存器AX | AX = BX |
| add ax, bx | 将AX,BX 中的内容相加, 结果存在AX中 | AX = AX + BX |
(原AX中的值:0000H, 原BX中的值:0000H)
| 程序段中的指令 | 指令执行后AX中的数据 | 指令执行后BX中的数据 |
|---|---|---|
| mov ax, 4E20H | 4E20H | 0000H |
| add ax, 1406H | 6226H | 0000H |
| mov bx, 2000H | 6226H | 2000H |
| add ax, bx | 8226H | 2000H |
| mov bx, ax | 8226H | 8226H |
| add ax, bx | 044CH(?) | 8226H |
| add al, 85H | 00C5H | 4026H |
| add al, 93H | 0058H(?) | 4026H |
8226H+8226H != 1044CH
因为AX 分为 AL 和 AH 所以 00C5H+93H != 0158H
但是不会丢失进制精度
物理地址
CPU访问内存单元时要给出内存单元的地址。所有的内存单元构成的存储空间时一个一维的线性空间.
16位结构的CPU
概括的讲,16位结构描述了一个CPU具有以下几个方面特征:
- 运算器一次最多可以处理16位的数据
- 寄存器的最大宽度位16位
- 寄存器和运算器之间的通路是16位的。
8086CPU给出物理地址的方法
8086有20位地址总线,可传送20位地址,寻址能力位1M.
8086内部为16位结构,它只能传送16位的地址,
表示出的寻址能力却只有64k
地址加法器互作原理
地址加法器合成物理地址的方法:
物理地址 = 段地址*16+偏移地址
| 移位位数 | 二进制 | 十六进制 | 十进制 |
|---|---|---|---|
| 0 | 10B | 2H | 2 |
| 1 | 100B | 4H | 4 |
| 2 | 1000B | 8H | 8 |
| 3 | 10000B | 10H | 16 |
| 4 | 100000B | 20H | 32 |
段的概念
错误认识: 内存被划分成了一个一个的段,每个一个段有一个段地址。
- 段地址*16 必然是16的倍数,所以一个段的起始地址也一定是16的倍数
- 偏移地址位16位,16位地址的寻址能力为64k, 所以一个段的长度最大为64k.
"数据在21F60H内存单元中。" 对于8086PC机的两种描述:
- 数据存在内存2000:1F60单元中;
- 数据存在内存的2000段中的1F60H单元中。
段寄存器
段寄存器就是提供段地址。
8086CPU有四个段寄存器:
CS: 代码段地址寄存器
DS:数据段地址寄存器
SS: 堆栈段地址寄存器
ES:其他的不够用所用的段地址寄存器
CS和IP
CS和IP是8086CPU中最关键的寄存器,它们指示了CPU当前要读
取指令的地址。
CS 为代码段寄存器
IP为指令指针寄存器(指向的是偏移地址)
同时修改CS,IP的内容
JMP 段地址:偏移地址 -》 JMP 2AE3:3 物理地址 2AE33H
-> JMP 3: 0B16 物理地址 0B46H
DEBUG
R命令查看,改变CPU寄存器的内容
D命令查看内存中的内容
E命令改写内存中的内容
U命令将内存中的机器指令翻译成汇编指令
T命令执行一条机器指令
A命令以汇编指令的格式在内存中写入一条机器指令。
寄存器(内存访问)
内存中字的存储
在0地址处开始存放20000 (4E20H)
字节型数据只占一个字节(8位数据)
字型数据占连续两个字节(16位数据)
DS和【address】
如何把1000H送入到ds?
传送指令mov ax, 1
相似的方式 mov ds,1000H (不能这么做) 属于硬件设计问题
数据-》通用寄存器-》段寄存器
mov bx, 1000H
mov ds, bx
mov [0], al
SUB是减法运算。
比如 mov ax,2 mov bx,1 sub ax,bx
其中sub ax,bx就是ax中的值减bx中的值,等于1,然后把结果,也就是1,放入ax中。
mov , add, sub指令
mov 通用寄存器, 数据 mov ax , 6
mov 通用寄存器, 寄存器 mov bx, ax
mov 通用寄存器, 内存单元 mov ax, [0]
mov 内存单元, 寄存器 mov [0], ax
mov 段寄存器, 寄存器 mov ds, ax
add 寄存器, 数据 add ax, 8
add 寄存器, 寄存器 add ax, bx
add 寄存器, 内存单元 add ax, [0]
add 内存单元, 寄存器 add [0], ax
sub 寄存器, 数据 sub x, 9
sub 寄存器, 寄存器 sub ax, bx
sub 寄存器, 内存单元 sub ax, [0]
sub 内存单元, 寄存器 sub [0], ax
比如我们用123B0H~~~123B9H这段空间来存放数据
段地址: 123BH
长度:10字节
CPU提供的栈机制
现今的CPU中都有栈的设计
8086CPU提供相关的指令来以栈的方式访问内存空间
8086CPU提供入栈和出栈指令:
PUSH(入栈)
POP(出栈)
push ax: 将寄存器ax中的数据送入栈中
pop ax: 从栈顶取出数据送入ax
8086CPU的入栈和出栈操作都是以字为单位进行的
注意:字型数据用两个单元存放,高地址单元放高8位,低地址单元放低8位。
CPU如何指导当前要执行的指令所在的位置?
寄存器CS和IP中存放着当前指令的段地址和偏移地址。
8086CPU中,有两个寄存器:
段寄存器SS 存放栈顶的段地址
寄存器SP 存放栈顶的偏移地址
任意时刻,SS:SP指向栈顶元素。
push ax
- SP=SP-2
- 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶
段寄存器都是以s结尾的,通用寄存器都是以x结尾的
push, pop指令
push和pop指令的格式
push内存单元:将一个内存单元处的字入栈(栈操作都是以字为单位)
pop内存单元: 出栈,用一个内存字单元接受出栈的数据
例如: push[0] pop[2]
指令执行时,cpu要知道内存单元的地址,可以在push, pop指令中给出内存单元的偏移地址,段地址在指令执行时,cpu从ds中取得。
mov ax,1000H
mov ss,ax
mov sp, 0010H
mov ax, 002AH
mov bx, 002BH
push ax
push bx
pop ax 就是把栈顶的bx放入ax中
pop bx 就是把栈中的ax放入bx中
第一个程序
我们将开始编写完整的汇编语言程序,用编译器将他们编译成为可执行文件(如:*.exe文件),在操作系统中运行。
- 使用汇编语言编译程序(MASM.EXE)对源程序文件中的源程序进行编译,产生目标文件;
- 再用链接程序(LINK.EXE) 对目标文件进行链接,生成可在操作系统中直接运行的可执行文件。
可执行文件
可执行文件中包含两部分内容:
程序(从原程序中的汇编指令翻译过来的机器码)
数据(源程序中定义的数据)
源程序
汇编指令: 有对应的机器码的指令,可以被编译位机器指令,最终位CPU所执行
伪指令: 没有对应的机器码的指令,最终不被CPU所执行。
谁来执行伪指令呢?
伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。
定义一个段
segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。
end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。
assume: 含义为假设
它假设某一段寄存器和程序中的某一个用segment ... ends 定义的段相关联。
汇编程序:
伪指令 (编译器处理)
汇编指令 (编译为机器码)
程序:源程序中最终由计算机执行,处理的指令或数据。
将源程序文件中的所有内容称为源程序,将源程序中最终由计算机执行处理的指令或数据,成为程序。
程序最先以汇编指令的形式存在源程序中,经编译链接后转变为机器码,存储在执行文件中。
源程序
任务:编程运算2的3次方
abc segment
mov ax,2
add ax,ax
add ax,ax
abc ends
end
| 目的 | 相关指令 | 指令性质 | 指令执行者 |
|---|---|---|---|
| 通知编译器一个段结束 | 段名 ends | 伪指令 | 编译时,由编译器执行 |
| 通知编译器程序结束 | end | 伪指令 | 编译时,由编译器执行 |
| 程序返回 | mov ax,4c00H int 21H | 汇编指令 | 编译时由CPU执行 |
未完待续
(推荐)有点编程基础的
b站小甲鱼,我看的是这个up主的汇编
学jvm去看b站尚硅谷看宋红康的
计算机组成原理(b站去看哈工大的)
操作系统(b站去看哈工大的)
计算机网络(b站去看哈工大的)
数据结构我比较菜,就不推荐了。
点个赞吧!讨生活啊,大哥大姐们。