第一章 基础知识

  • 存储器(内存)存放CPU工作的指令和数据(CPU可以直接使用的信息在内存中存放);指令和数据都是二进制数没有任何区别,由CPU决定是数据还是指令
  • 内存单元:存储器被分为若干个存储单元,并从0开始编号(存储单元的地址),一个存储单元为1字节(8bit)
  • CPU的读写

总线逻辑上分为:地址总线、数据总线、控制总线

  • 地址总线:地址线宽度决定了CPU的寻址能力,计算方式 :2^[地址线宽](个内存单元)
  • 数据总线:决定了CPU和外界的数据传输速度(8根数据总线可传送一个8位(bit)二进制数,即1个字节)
  • 控制总线:是各外部器件的不同控制线的集合

CPU进行数据读写必须经过3类信息交互:

①存储单元的地址(地址信息)②器件的选择,读或写的命令(控制信息)③读或写的数据(数据信息)

读:CPU在内存中读取数据时,要先指定存储单元的地址(你要找一个地方先要确定一个地址),会把要读取的地址经过地址总线发给内存;同时CPU控制器将内存读命令通过控制总线发送给内存,并通知内存要读取数据;最后内存将被指定的内存单元中的数据经过数据总线送入CPU

写:与读类似,CPU经地址线发送要操作的内存单元的地址,CPU经控制线将内存写命令发送至内存,并通知内存要写入数据;CPU通过数据线将数据送入指定的内存单元;

内存地址空间:

  • 每一个外部器件都有自己的存储芯片(如显卡有显存RAM和ROM(装有显卡BIOS)、网卡ROM(装有网卡BIOS)),CPU控制各个设备都是通过总线向各个设备的存储芯片发送命令,存储芯片根据CPU的命令控制外设进行工作
  • 所有的物理存储器被看作一个由若干存储单元组成的逻辑存储器,每个物理内存在这个逻辑内存中占有一个地址段,即一段地址空间可看出各存储芯片都和CPU的总线相连;CPU对它们的读写都通过控制线发出内存读写命令
  • CPU根据读取不同的地址实现对不同设备的读写操作,这个逻辑存储器就是内存地址空间,它的容量受CPU寻址能力的限制(即地址总线宽度限制),如有20位的地址总线宽度,它的寻址能力为2^20个内存单元(一个存储单元为1字节(8位))所以该CPU的内存地址空间的大小为1MB;32位地址线宽的CPU内存地址空间最大为为4GB(CPU不行的话加内存条也没得用!64位的就不得了了,主板不够插)

1、CPU寻址能力 = 2^线宽

2、一根数据总线传一位数据,8根数据总线一次传8位数据(1Byte)

第二章 寄存器

CPU组成:运算器(信息处理)、控制器(控制各种器件进行工作)、寄存器(信息存储)

内部总线实现CPU内部器件的联系

外部总线实现CPU与主板和其他器件的联系

  • AX、BX、CX、DX通常用来存放一般性数据——通用寄存器(后面是X的寄存器是16位的,现在的EAX前面加了个E是32位)
  • 这四个寄存器都可以分为两个独立的八位寄存器使用(如AX可分为高位AH和低位AL),是为了向下兼容(只使用低位,高位填0)单独使用时当成一个来看,同时使用时是整体(计算方法 2^[位数] )
  • 一个字=两个字节=>一个十六进制数,所以十六进制数的一位相当于二进制数的四位
  • 汇编指令不分大小写
  • 16位结构的CPU具备以下特征(64位同理):1、运算器一次最多可以处理16位的数据;2、寄存器的最大宽度为16位;3、寄存器和运算器之间的通路是16位的;
  • 8086CPU给出物理地址的方法:

8086有20位地址总线,可传送20位地址,寻址能力为2^20 = 1M,

而8086内部为16位结构,他只能传送16位的地址,表现出的寻址能力只有64,

说明CPU不能直接传送16位数据地址到20位的总线上(资源浪费),所以需要转换成20位的地址;

8086采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址(段地址 和 偏移地址),经过地址加法器转换成20位的物理地址,示意图:

地址加法器的工作原理:物理地址 = 段地址SA*16+偏移地址EA  &  物理地址 = 基础地址 + 偏移地址

相当于把段地址往高位进了一位,这里说的16位是二进制的数,CPU中存储的数据只能是二进制,而我们表示地址是用16位的数字,前面说了2和16进制的转换关系,一个十六进制数的位等于四个位的二进制数,所以段地址乘以16,把段地址后移了一位,增加了一位16进制数,二进制就得加四位,即数据左移四位(二进制位),16+4=20位,转换完成

  • 一个数据的X进制形式左移1位,相当于乘以X(十进制数乘十后左移一位)
  • 一个数据的二进制形式左移N位,相当于该数据乘以2的N次方

段落的概念:

  • 内存本身并没有被分段,分段概念来自于CPU,8086CPU用 物理地址 = 段地址*16+偏移地址 的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存
  • 用 段地址x16 定位段的起始地址,用偏移地址定位段中的内存单元

注意:1、段地址X16必然是16的倍数,即一个段的起始地址也一定是16的倍数

2、偏移地址为16位,16位地址的寻址能力为64k,所以一个段的长度最大为64k

  • CPU访问内存单元时必须向内存提供内存单元的物理地址(有地址才知道要访问哪里)
  •       CPU可以用不同的段地址和偏移地址形成同一个物理地址(段地址+偏移地址都等于物理地址)
  • 偏移地址EA为16位,变化范围0~FFFFH,仅用偏移地址来寻址最多可寻64k个内存单元(如段地址位1000H,那么CPU寻址范围为:10000H~1FFFFH
  • 储存单元的地址用 段地址 和 偏移地址 描述:数据在21F60中 a、数据存在内存2000:1F60单元中;b、数据存在内存的2000段中的1F60中;(可将地址连续、起始地址为16的倍数的一组内存单元定义为一个段)

段寄存器:

  • 提供段地址,8086CPU有4个段寄存器:CS(代码(指令)段寄存器)、DS(数据段寄存器)、SS(堆栈stack段寄存器)、ES(附加段寄存器)
  • CS和IP(指令指针寄存器)是8086CPU中最关键的寄存器,存放CPU当前要读取的指令的地址

在任何时候,CPU将CS为指定(存放)指令的段地址(代码段首地址),IP指定(存放)指令的偏移地址(指令从哪处代码开始执行),CS和IP经过地址加法器加工后(通过输入输出控制电路)从地址总线指向内存单元读取指令,指令再通过数据总线(经过输入输出控制电路)传递给指令缓冲器,再到执行控制器,实现执行效果

  • 内存中被CPU执行过的代码必然被CS:IP指向过
  1. 从 CS : IP 指向内存单元读取指令,读取的指令进入指令缓冲器
  2. IP = IP + 所读取指令的长度,从而指向下一条(即所指向的指令执行完后接着运行接着的下一条指令)
  • CPU加电启动或复位时,CS=FFFFH,IP=0000H,即CPU刚启动时读取并执行的第一条指令是FFFF0H

修改CS、IP值的指令:转移指令 jmp

  1. 同时修改CS、IP的内容:jmp 段地址:偏移地址 (例:jmp 2AE3:3)
  2. 只修改IP的内容:jmp 某一合法寄存器(jmp ax),用寄存器中的值修改IP

代码段:

  • 根据需要,将一组内存单元定义为一个段:把长度<=64kb的一组代码存在一组地址连续、起始地址为16的倍数的内存单元中(个人理解为偏移地址需要16位的位置),这段内存用来存放代码,从而定义了一个代码段 (代码段不能影响CPU来是否执行它,还是得看CS:IP所指向的内存单元中的内容为指令,代码段仅仅是一种编程格式)
  • 所以要将CS:IP指向所定义的代码段中的第一条指令的首地址

debug命令:

  • R 查看、改变CPU寄存器的内容(修改寄存器中的值:r [寄存器名])
  • D 查看内存中的内容 ( d 段地址:偏移地址 )
  • E 改写内存中的内容
  • U 将内存中的及其指令翻译成汇编指令
  • T 执行一条机器指令
  • A 以汇编指令的格式在内存中写入一条机器指令

第三章 寄存器(内存访问)

  • 字单元:存放字型数据的内存单元

一个字等于两个字节,一个字节等于8比特,则一个字型数据有16位;

因为有两个字节组成,字可分为高位和低位,图中0和1可组成一个字,1位比0位高,所以他们组成的字,高位是4E,低位是20即4E20(可以直接用字的起始地址描述它,如0地址字单元)

任何两个地址连续的内存单元,可以将其看成一个内存字单元,一个为字低位字节单元,一个为字高位字节单元

DS寄存器 和 [address]

  • DS寄存器:用来存放要要访问数据的段地址(首地址),配合 [ EA ] 使用,[ ] 说明操作的是一个内存单元,EA为偏移地址,段地址为DS中存放的地址
  • 数据段:将一组长度小于64k、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段;具体操作时用ds存放数据段的段地址,在根据需要用相关指令访问数据段中的具体单元

栈(stack):出入栈规则LIFO(后进先出)

  • 入栈:push         出栈:pop

push 寄存器           pop 寄存器

push 段寄存器      pop 段寄存器

push 内存单元      pop 内存单元

  • 内存空间是如何被当做栈使用的:

每执行一次入栈指令,都会将寄存器的内容放入栈顶单元的上方,此时段寄存器SS、寄存器SP就会存放栈顶的地址及偏移量,任何时候SS:SP都指向栈顶元素,执行push和pop时,CPU从SS和SP中获取段顶地址

入栈时:SP=SP-2  (入栈时由高位往低位走)

出栈时:SP=SP+2  (出栈时由低位往高位走)

注意:入栈时的偏移量SP的取值要比当前栈最高位+1位(如要入栈至1000E~F(即栈最底部的字单元地址000E),SP值应比F高一位0010

  • 栈顶越界:需自行根据所安排的栈大小进行出入栈,避免入栈数据太多越界,也要避免空栈的时候继续出栈导致越界;越界会覆盖或修改掉可能是其他程序的内存数据或指令,需要注意!
  • push执行时,CPU改变栈顶的指向,即SP=SP-2,再将数据传入SS:SP指向的字单元中;

pop执行时,CPU先读取栈顶指向的字单元数据,再改变SP,即SP=SP+2;

  • 可见push、pop指令修改的只是SP,栈顶的变化范围为:0~FFFF
  • 栈操作机制:SS:SP指示栈顶;改变SP后写内存的入栈指令;读内存后改变SP的出栈指令
  • Debug的 T 命令在执行修改寄存器SS的指令时,下一条指令也紧接着被执行(mov ss,ax ; mov ss,[0] ; pop ss)
  • 可用段寄存器表示内存单元的段地址:

第四章 汇编程序

  • 编写汇编源码----编译连接----可执行文件(包含由汇编指令翻译过来的机器码和源程序中定义的数据以及相关的描述信息,如程序大小,占用多少内存空间等)
  • 伪指令:

段名 segment         ;定义一个段,该段从此开始

:

段名 ends                ;该段从此结束


end:汇编程序结束的标记

assume:含义为“假设”,假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联,用于说明关联的关系。格式:assume 寄存器名:段名

  • 程序返回:DOS为例,可执行文件P2想要运行,必须有一个正在运行的程序P1,要CPU将P1的运行权限交给P2,P2才能执行,且执行结束后需要将权限返还给P1,用到汇编指令 mov ax,4c00  int 21 (十六进制),结束相关的概念:

  • 自定义的段名标号代指了一个地址,最终被编译、连接的程序处理为一个段地址
  • Link连接的作用:
  1. 当源程序很大时,可分为多个源程序文件来编译,各编译为目标文件后,再用连接程序将他们连接到一起,生成一个可执行文件;
  2. 程序中调用了某个库文件的子程序,就要把这个库文件和程序的.obj目标文件连接到一起,生成一个可执行文件;
  3. 源代码编译后,得到有机器码的.obj目标文件,但有些内容不能直接用来生成可执行文件,连接程序Link.exe把这些内容处理为最终的可执行信息;所以,即使只有一个原文件,且不调用库文件,还是要使用连接,生成可执行文件;

  • 在DOS中运行程序时,由command根据文件名找到这个程序,并加载到内存中,设置CS:IP指向程序的入口,command暂停运行,CPU运行程序,程序运行结束后,返回command;
  • DOS系统的shell(外壳)程序,就是command.com程序,负责处理各种输入:命令或程序的文件名;
  • DOS中.EXE文件中程序的加载过程:
  1. 程序加载后,DS存放着程序所在的内存区的段地址,且偏移地址为0,即程序所在的内存区地址为DS:0
  2. 而这个内存区的前256个字节中存放的是PSP,DOS用来和程序进行通信,往后推256字节的空间存放的就是程序

所以,从DS中可以得到PSP的段地址SA:0,则实际的物理为SAx16+0(x16段地址后移一位),因为PSP占256(100H)字节,所以程序部分的物理地址是:SAx16+0+256 = SAx16+16x16+0 = (SA+16)x16+0

可用段地址和偏移地址表示为:SA+10H:0  (SA进位也要x16,而16x16为100H,根据上面的公式结果,各抵消一个x16(一个十六进制的进位),得出此结果)

也就是DS寄存器存放的地址SA+10H就是程序的段地址,CS:IP会指向这里(程序入口)

第五章 [BX]和loop指令

  • [BX]:与[]一样,表示一个内存单元;[0]表示偏移地址为0,[BX]表示偏移地址为BX寄存器中的值

完整描述一个内存单元需要知道的两个信息:①内存单元的地址;②内存单元的长度(类型)

  • loop:通过跳转实现循环(类似C语言goto语句)

程序结构:

mov cx,循环次数

s:

循环执行的程序段

loop s

  1. CX寄存器存放循环次数
  2. CPU执行loop s 时,要进行两步操作:(且按照①②的顺序)

①(CX)=(CX)- 1;

②判断CX中的值,不为0则跳转至标号标识的地址处执行,为0则执行下一条语句

标号会被自动替换成所标记的地址显示在源程序中,cx-1不为0时,“loop 地址”会把IP的值设置成这个“地址”,从而使CS:IP指向“地址”处,实现跳转

  • 符号“ ( ) ” :用于描述元素或数据

“()”中的元素可以有3种类型:①寄存器名;②段寄存器名;③内存单元的物理地址(一个20位数据)

可描述的数据有两种类型:①字节;②字 (同时类型说明了数据的长度)

  • 约定符号idata表示常亮

在汇编程序中,数据不能以字母开头;所以,ffffh书写时前面要加0,即0ffffh

  • debug用于跳过循环的指令:p直接执行到cx为0;g 偏移地址,直接执行到偏移地址所在处,如,g 0016,表示直接执行到CS:0016处(不禁发起疑问:这就是断点?)
  • Debug和汇编编译器masm对指令的不同处理:

[idata]在debug中解释为内存单元“idata”为偏移地址;而masm中解释为常量“idata”,如mov ax,[4]就为mov ax,4 不能达到预想效果;

解决办法:①用[bx],间接存储偏移地址,如 mov ax,[bx] ;②[]前面显示注明段地址所在的段寄存器(段前缀),如 mov ax,ds:[4]

第六章 包含多个段的程序

  • 在代码中使用数据:
  1. dw 数据.1,数据2,数据3      dw为“define Word”,定义字型数据,如dw在段首定义数据,那么数据的偏移地址从0开始,即CS:0 ;
  2. dw 0,0,0,…   可以用于开辟内存空间,如给栈开辟内存空间
  3. 由于段首存放数据,所以需要指定程序入口地址:在程序结束的 end 汇编伪指令后加 start 标号,同时用start指定入口的位置,结构框架:

  • 将数据、代码、栈放入不同的段,定义形式:段名 segment … 段名 ends

注意:CPU处理段中的内容完全依靠程序中具体的汇编指令,和汇编指令对CS:IP、SS:SP、DS等寄存器的设置来决定的,即把他们指向对应的内存,那么对应的内存段就被被CPU当成对应的内容,与段的命名、assume后的定义等无关(但assume后定义的段名可以代替对应的寄存器来表示寄存器的内容,它们之间有一种联系);

  • 每一个段寄存器只有和对应的偏移地址寄存器配合起来才能指向对应的内存(如CS:IP指向栈顶),其他时候都可以作为一个段寄存器来使用(如 SS:[bx])
  • 使用汇编指令进行内存单元的存取操作都要经过通用寄存器(如 add ds:[bx],ax),不能内存单元之间直接进行(如mov ds : [bx],ss:[bx])

第七章 更灵活的定位内存地址的方法

  • ‘与’指令and(将操作对象的相应位设为0)、‘或’指令or(将操作对象的相应位设置为1);常用于改变字母大小写,大写字母ASCII码第5位为0,小写的为1
  • [bx+idata]代表内存单元偏移地址,几种使用格式:ax,[200+bx]、ax,200[bx]、ax,[bx].200;还可以以数组的形式来操作:0[bx]、5[bx]  (起始段地址为0和5的两组数据),为高级语言实现数组提供了便利机制(就像C语言的a[i]、b[i]);也可以直接寄存器相加得出最终偏移地址EA(如,mov ax,[bx+si]或mov ax,[bx][si])
  • si和di寄存器(功能类似bx寄存器,但不能分为bh、bl两个八位寄存器)
  • CPU的几种寻址方式
  1. [idata]用一个常量来表示地址,可用于直接定位一个内存单元
  2. [bx]用一个变量来表示内存地址,用于间接定位一个内存单元
  3. [bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元
  4. [bx+si]两个变量
  5. [bx+si+idata]两变量一常量
  • 程序中暂存一个数据往往使用用栈(嵌套循环就需要用此暂存CX的值)

学_汇编语言_王爽版 要点采集笔记(未完待续&hellip;)的更多相关文章

  1. C程序员学bash shell容易掉坑的注意点(未完待续)

    shell解释器很娇气,有一点点不合乎规范的编码风格都会让脚本歇菜. 1. 空格该有还是该没有要看情况.该有的时候不能没有!该没有的时候不能有! 变量赋值的等号两边不能有空格. 2. 在shell中是 ...

  2. Reading | 《数字图像处理原理与实践(MATLAB版)》(未完待续)

    目录 一.前言 1.MATLAB or C++ 2.图像文件 文件头 调色板 像素数据 3.RGB颜色空间 原理 坐标表示 4.MATLAB中的图像文件 图像类型 image()函数 imshow() ...

  3. 省钱版----查找 IoT 设备TTL线序__未完待续

    作者:仙果 原文来自:省钱版—-查找 IoT 设备TTL线序 省钱版----查找 IoT 设备TTL线序__未完待续 缘由 在IoT固件调试分析的过程中,建议首先在IoT设备的板子上焊接调试线,这是能 ...

  4. 关于《汇编语言(王爽)》程序6.3使用16个dw 0的问题

    在学习王爽老师<汇编语言>的第6.2节时,在程序6.3代码中,给出了如下的代码: assume cs:code code segment dw 0123h, 0456h, 0789h, 0 ...

  5. 应中DOS中断显示字符串(摘自《汇编语言》王爽)

    data segment s1 db 'Good,better,best,$' s2 db 'Never let it rest,$' s3 db 'Till good is better,$' s4 ...

  6. 自学自用 = B站(操作系统_清华大学(向勇、陈渝)) 未完待续。。

    视频地址 https://www.bilibili.com/video/av6538245 介绍 本篇博客,旨在记录视频学习的要点,所以格式随意, 方便本人日后自考和回忆,有兴趣的朋友可以评论讨论. ...

  7. Python入门_汇总_未完待续

    if/elseif/else for while break continue 多重循环 list [] duple() dict {} set {[]} 函数 help(abs) 查看abs函数的帮 ...

  8. java线程详细版(未完待续)

    1. Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一 ...

  9. qq面板(仿版,未完待续中。。。。)---2017-04-24

    主要实现效果: 1.点击对话,显示对话:点击联系人,显示联系人 2.在联系人界面: 实现好友列表的展开与折叠:(图12) 实现鼠标移到好友列表上的背景颜色的变化:(图3) 选中的好友背景颜色改变(图4 ...

随机推荐

  1. 【Linux】awk笔记

    awk是一种处理文本文件的语言,是一个强大的文本分析工具. 实例 ①显示文件行中匹配项 # 每行按空格或TAB分割,输出文本中的1.4项 yunduo@yunduo-ThinkCentre-XXXX: ...

  2. Visual Studio Team Services使用教程【3】:默认团队权限说明

    2017.4.23之后建议朋友看下面的帖子 TFS2017 & VSTS 实战(繁体中文视频) Visual Studio Team Services(VSTS)与敏捷开发ALM实战关键报告( ...

  3. rest_framework框架之认证功能的使用和源码实现流程分析

    rest_framework框架之认证的使用和源码实现流程分析 一.认证功能的源码流程 创建视图函数 Note 创建视图函数后,前端发起请求,url分配路由,执行视图类,视图类中执行对应方法必须经过d ...

  4. 如何把对象手动注入Spring容器并实现依赖注入

    将对象注入到Spring容器并实现依赖注入 public class UserDao { @Resource AccountService accountService; public void pr ...

  5. 001JZ2440开发板熟悉与使用

  6. 基于 HTML5 WebGL 与 WebVR 3D 虚实现实的可视化培训系统

    前言 2019 年 VR, AR, XR, 5G, 工业互联网等名词频繁出现在我们的视野中,信息的分享与虚实的结合已经成为大势所趋,5G 是新一代信息通信技术升级的重要方向,工业互联网是制造业转型升级 ...

  7. 双系统,重装windows 无法进入Windows安装界面

    解决办法 windows引导并没有被更新 进入linux 更新grub sudo update-grub 然后重启电脑,进行下一步安装 原理 grub是引导操作系统的程序,它会根据自己的配置文件,去引 ...

  8. Java并发-Java内存模型(JMM)

    先来说说什么是内存模型吧 在硬件中,由于CPU的速度高于内存,所以对于数据读写来说会出现瓶颈,无法充分利用CPU的速度,因此在二者之间加入了一个缓冲设备,高速缓冲寄存器,通过它来实现内存与CPU的数据 ...

  9. react路由的跳转和传参

    1.路由的跳转 一.DOM跳转 在需要跳转的页面导入import {Link} from 'react-router-dom',在需要跳转的地方使用link标签的to属性进行跳转,路由配置文件中导出的 ...

  10. rabbitmq系列(一)初识rabbitmq

    为什么要使用消息中间件 案例:假如我们开发了一个商品抢购网站.这个网站的目的就是在某一时间点进行抢购商品,同时要求用户注册,在注册的时候会同时给用户电话和邮箱中发送验证码,以便完成信息注册.传统做法应 ...