汇编_王爽第二章小结

       一个典型的 CPU 由 运算器,控制器,寄存器 组成等器件组成,这些器件靠内部总线相连,内部一词相对于cpu外部和其他器件连接的总线(外部总线一词相对而言)

       在 CPU 中,程序员能够用指令读写的部件只有 寄存器 ,程序员可以通过改变寄存器中的内容实现对 CPU 的控制。

       补充一下:
              不同的 CPU ,寄存器的个数,结构是不同的,8086 CPU 有 14 个寄存器分别是:
                      AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW
              win32 汇编上有 eax,ebx,ecx,edx,esi,edi,esp,ebp,eip,eflags,ax... ,
              win64 汇编上有 rax,rbx,rcx,rdx... 自己斟酌这些规律,当然, 寄存器功能上可能有些小小差别。


8086 CPU 的所有寄存器都是 16 位的,可以放两个字节。

       通用寄存器: AX,BX,CX,DX
               这 4 个寄存器通常用来存放一般性的数据,虽然他们在某些时候,有着特殊的用法,比如: 乘除法 乘数和被除数以及结果需要用到 ax 或 ax,dx,端口数据读取需要用到 ax 或者 al,中断例程子程序调用选择用到 ah ...
               他们都是 16 位寄存器,从 0 为最小值,最大值就为: 2^16-1, 一位上要么是 0 要么是 1。所以最小值: 0000000000000000B ,最大值为:1111111111111111B (B 表示这是一个二进制数)

8086 CPU 的上一代 CPU 中的寄存器都是 8 位,为了保证兼容,使原来基于上代CPU编写的程序稍加修改就可以运行在 8086 之上

       8086 CPU 的 AX,BX,CX,DX 这 4 个寄存器都可以分为可独立使用的 8 位寄存器来用:
               即:AX==> AH和AL ; BX==> BH和BL ; CX ==> CH和CL ; DX ==> DH和DL

       以上面的 AX 为例子:
              AX中的0-7 位数据构成 AL的值,AX 中的 8-15 位构成 AH 的值
                     也就是说: AH 或者 AL 都是 8 位大小的二进制数据
               举个例子:
                      数据: 18  (这里是 十进制 数据 数据后面没有任何标志,但这样可不方便表达较大的数据)                       二进制表示: 100111000100000B
                      十六进制: 4E20H   (以 H 结尾的数据为 十六进制数据)
                      在寄存器AX中的存储: 0100111000100000B
(AH) == 78 == 4EH ; (AL) == 32 == 20H ; 78 和 32 =? 20000 但是 4E 拼接 20 得出 4E20H == 20000

8086 CPU 一次可以处理以下两种尺寸的数据:
        字节(byte) 和 字(word) ;

              字由两个字节组成,长度为 16 位二进制数据
                     所以 正好 AH 能存一个字节,AX 能存一个字。
        补充: 上面提到 4E20H ==> 4H==0100B == 4 ; EH == 1110B == 14 ; 2H == 0010B == 2 ; 0H == 0000B == 0 这么看来 16 进制似乎比 十进制更直观。以后用的 16 进制特别频繁。

程序员能读写的指令只有 寄存器 。我们可以用 mov 这个传送指令 对通用寄存器进行修改

指令格式:
					mov reg,data	; reg 表示 通用寄存器,data 表示数据 ==》 mov ax,8
					mov reg,reg		;
					mov reg,[data]	; [data] 表示内存单元,段地址从 ds 段中找,data 跟上面一样是数据 ===> mov ax,[8]
					mov [data],reg
					mov 段寄存器,reg

``
       物理地址:
              CPU 在访问内存单元的时候,要给出内存单元的地址,所有内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间上都有唯一的地址,称之为物理地址。
              上一节讲过: CPU 要想进行数据的读写,必需和外部器件(芯片)有3类信息交互:
                            1.存储单元的地址(地址信息) 器件的选择 ||
                            2.读写的命令(本人理解为寄存器操作,控制信息)  ||
                            3. 读或写的数据(数据信息) ||

       那么第一件事肯定是寻址(哪怕你写的立即数,也要寻址),CPU 通过地址总线送入存储器,必需是一个内存单元的物理地址。

       在 CPU 向地址发出物理地址之前,必须要在内部先形成这个物理地址。 (不同的 CPU 可以有不同的形成物理地址的方式)。
       插曲: 物理地址也称 实地址 ,对应的有 虚拟地址 ,毕竟必要把程序的代码安排在实际物理地址上时,那个物理地址又不是向 BIOS 芯片那样(每次启动都会准备数据,然后把执行权交给系统,所以不变化),这样再多的地址也不够你每天安装的软件使用
       大佬们引入 虚拟地址,分段,分页 等概念去组织程序去合理利用物理地址,这种运算挺复杂,本人还没完全搞清,当然本书可没介绍这些。
       现在 讨论 8086 CPU 是如何在内部形成内存单元的物理地址的。
              8086 是 16 位 CPU 16位机特征如下:
                     运算器一次最多可以处理16位的数据
                     寄存器的最大宽度为16位。
                     寄存器与与运算器之间的通路为16位。
              也就是说: 在 8086 内部,能够一次性处理,传输,暂时存储的信息的最大长度是16位。去内存地址上找的数据,一次最大也只能是16位,你可以让它多次去做。

       8086 CPU 有 20 根地址总线,可以传送 20 位地址,寻址能力是 1 MB,但是因为是16位的,所以一次能传送,处理 16 位,所以表现出的寻址能力为 64 KB。
       如何更有效的寻址?
              该 CPU 相关部件提供两个 16 位的地址,一个称之为 段地址,一个称之为偏移地址。
       通过地址加法器部件,将两个地址进行 (段地址*16 + 偏移地址) 的运算,得出具体的 20 位物理地址. 因为当时听节约内存的.
       你问为什么这么计算?
              地址肯定是相加的,这没问题,*16 == *2^4,如果你熟悉二进制数的话, 一个二进制数左移4位,移动后的右边用0补充,其实就等于将那个数值*16,
       这样不就补充 4 位了?
       段地址是什么?偏移地址?
              一种称呼而已,只是因为存放的寄存器不同而已,段地址存放在段寄存器中,偏移地址是相对于段上的距离而言的(这里是本人的理解,觉得不对请忽略)。
       段?
              内存中其实没有段的概念,但是为了我们方便使用,也为了方便芯片的操作,我们可以认为 某个地址到某个地址 之间的内存单元组成一个段,这个段专门用于做某些工作。
              比如: 后面好多章后才会学到的 0B800H段 上,写入的数据会在显示屏上展示,然后用偏移地址决定它具体在屏幕的那个位置,对于 32 位机器可直接 cmd 中搞,64位的,用 dosbox.exe 操作
       注意: 因为上面的算式,CPU可以用不同的段地址和偏移地址形成同一个物理地址。
为了方便表述:
              像 数据在 21F60H 内存单元中,应尽量表述为: 数据在 内存 2000:1F60 单元中,又或者说: 数据在 内存 2100:0F60 单元中,建议前者。


       段寄存器: CS,SS,DS,ES
              这 4 个寄存器用于存放和提供 段地址。也正是上面寻址中要的 段地址
              首先是 CS 段,对应的偏移地址存放在 IP 寄存器中
                     于是 CS:IP 指向的内容就是 CPU 要找的数据,CPU 会把这个数据当成可执行的指令,但不是什么数据都可以被执行,至少应该是 CPU 可以理解的 二进制数
                     也可以这么表述: 8086 机器中,CPU 将 CS:IP 指向的内容当做指令执行。
              修改 CS:IP 的指令
                     程序员能读写的指令只有 寄存器 。我们可以用 jmp 这个跳转指令 对 CS:IP 进行修改,这个是无条件跳转指令,会让 CPU 无条件的去执行某地址上的代码

		格式: jmp CS_VALUE:IP_VALUE 或者 jmp reg	; CS_VALUE:IP_VALUE 对应上面物理地址中的 表述方式。 reg 指的是 寄存器
				比如: jmp 2000:1F60  	;或者  
						 	mov ax,2000h  
						 	mov cs,ax 
						 	mov ax,1f60h  
						 	jmp ax	;
			
			
			;IP ,这个寄存器: CPU 在执行某条指令(指令本身而言就是内存单元的数据),都会记录执行的指令长度,并且让 IP += 这个长度,如此一来,CPU 读取道 IP 寄存器上的值,就知道下一条指令在哪了
			;这就是偏移作用,在一个段上找数据,偏移决定在那个段的具体那个位置,这是 8086 寻址方式。		
			; 这是我们人类理解方式
			
			;将一段内存当做代码段,仅仅是我们在编程时的一种安排。" 
			;CPU 只认 被 CS:IP 指向的内存所定义的代码段中第一条指令的首地址。"	
			; 机器理解方式
ps: 笔者在读这本书的时候,听说这是最好理解的一本书,读前几页就差点被劝退,挣扎好多次。为了后面能继续使用,请自行下载 DOSBOX.EXE 和 debug.exe 等相关 软件,方便编程实操。 对基础相关指令,请自行百度。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值