汇编学习 第二章

这是学习汇编语言的第二章的总结。

书上的内容(页数)虽然比第一章多,但是如果第一章理解完全后,第二章其实就是对第一章部分内容的深入操作。这一篇主要就把一些操作总结一下。

我们已经理解了存储器的物理地址:把所有硬件的存储单元,按照一定规定,线性排列,组成一个大的逻辑存储器,然后给每一个存储空间分配一个唯一的物理地址。

第二章主要就是从8086CPU的角度,去看一下,CPU如何玩弄内存
  • CPU主要配件
    • 运算器
    • 控制器
    • 内部总线
    • 寄存器

寄存器就是这一章的主角,CPU和内存交互时,需要临时保存各种数据或者指令(都是1和0),这些数据都是存在寄存器里的。8086是一个16位的CPU,他的寄存器都是16位的,也就是说能存16位二进制数据,4位十六进制。

            这里都是使用8086CPU来作为例子

寄存器分为几种,我们一个个来看

  • 通用寄存器
    AX,BX,CX,DX 这四个是通用寄存器,用来存放一般性数据,8086CPU是十六位的,上一代CPU是八位的,为了良好的兼容性,我们可以用AH去表示AX的高8位(High),AL去表示AX的低8位(Low)

     这里要注意一下:假设AX = 1100 0011 0101 1010 
     其中1100 0011 是AH  而  0101 1010 是AL
    

    这里嵌入一些我学习高级语言后的一些看法,错了请大佬拍砖。CPU如何操作,或者读取数据(二进制)其实都是我们告诉他的,对于底层一些已经写入CPU内部的规则,或者是应用层我们写的代码都是这样的。应用层数据会有int ,double,long 等等,其实就和AX和AH一样,我告诉你怎么处理这个数据,CPU就要按照我的规定去做。比如 char类型规定了是1个字节,然后我把这1个字节数据存进内存里,他就会在内存里占用8位二进制的大小,计算机看这8位数据,都是1和0,他就必须按照我的要求,完整的提取8位数据,而不是前4位+后2位,或者多读几位,都是不可以的。多了不行,少了也不行。这都影响提取数据后,换算的正确性。

    当我们写入寄存器时,也必须严格按照字节位
    1、AX = 0xFFFF AX+0x0001 = 0x0000
    2、AX = 0x1234 AH = 0x12 AL=0x34
    3、AX = 0xFFFF AH + 0x0001 => AX = 0xFF00 (溢出的会被截掉,AX,AH同理)
    4、截掉的数据并不是丢弃了,这里暂时不讨论这个。

  • 字(word)
    字是一个新的单位,1个字等于2个字节,正好是一个8086CPU,通用寄存器的大小

  • 汇编指令

    • add
      add ax,1 => ax = ax + 0x1
      add ax,bx => ax = ax + bx
    • mov
      mov ax,1 => ax = 0x1
      mov bx,ax => bx = ax
  • 8086CPU是16位CPU,但是他的地址总线是20位的,那就代表他的寻址空间更大了,提高了逻辑存储器的上限。
    我们来理一下关系:CPU内部指定寄存器会存着一个物理地址,然后通过地址总线定位到逻辑存储器的一个存储单元,然后控制总线给指定的硬件发送指令,最后数据总线进行数据传输。

      问题来了:16位的寄存器,怎么发出一个20位的物理地址
    

    这里 8086CPU就出现了分段的概念
    物理地址=段地址 左移4位 + 偏移地址

    1、段地址是什么?
    段地址是一个4位十六进制的数据,假设为0x1234,按照上面说的左移4位(二进制位)就会变成0x12340多了一位哦。
    2、偏移地址是什么?
    偏移地址也是4位十六进制数的数据,假设为0x1234,那他就是0x1234
    3、组合
    0x12340+0x1234=0x13574
    一共只能有5位十六进制,因为地址总线是20位二进制也就是5位十六进制。

      那谁来确定段该怎么分?
    

    这个是靠CPU来决定的,这只是CPU来表示20位十六进制物理地址的方式,并不是真的把内存分段。所以一个物理地质,可以通过多种多样的分段方法来体现。

  • 段寄存器 CS
    CS也是CPU的寄存器,CS是用来存储段地址的,也是16位的

  • 指令指针寄存器 IP
    IP也是CPU的寄存器,是用来存偏移地址的。

    8086CPU,会从CS:IP处开始执行一条指令,CS和IP有点大方向和微调的感觉。IP只有16位,如果CS不变,IP变化,最多也只能搜索到65536个内存单元。

      CPU会认为CS:IP指向内存单元都是指令而不是数据,
      如果已经看过书了,会发现读取一次CS:IP处的指令后,
      IP的值会自动增加,至于如何改变,应该是根据读取的是什么指令。
    

    具体的合并处理过程,记得看书哈,我这里简单走个图

    CS:IP=》地址加法器(组成5位十六进制)=》地址总线=》内存
    返回数据之后,IP的值会自己根据接收的数据指令,自动修改自己的值。

  • 汇编指令

    • jmp
      jmp可以用来修改CS和IP的值
    • jmp 100:99 => CS = 0x100 , IP = 0x99
    • jmp还可以单独修改IP的值
      jmp+合法寄存器:jmp AX => mov IP,AX
      注意,mov命令是不能修改IP和CS的,因为8086CPU不允许。

CPU唯一遵循的就是执行CS:IP所指向地址。

第二章剩下部分都是,实际操作问题,这里我大概说下我遇到的几个问题。

书上一些使用Debug去熟悉一些命令,第一,值都未必和你书上看到的一样(除了计算答案),
第二,书上实验会有一部分是让你往显存里直接修改内容,可能因为我是用模拟器的关系,所以显示不出来。

上面说的 add mov jmp 都是汇编指令,需要汇编编译器翻译成机器码,CPU才能看懂,我们还能通过Debug软件来直接测试学习8086CPU工作原理。

  • Debug命令(这里就列一下,具体看书,书上有图)
    • r 查看寄存器的值
    • r 寄存器 可以修改寄存器的值 “r ax” = 修改寄存器ax的值
    • d [xxxx:xxxx] [多少个] 用来查看逻辑存储器 “d 1000:100 1f” = 查看0x10100 处开始32个内存单元的值 (我用的bochs+freeDos模拟,这个命令后面不能加多少个。。。)
    • e 修改内存的值
    • u 查看指定内存内机器码对应的汇编指令
    • a 给内存直接写入汇编指令,add mov jmp这种
    • t 执行CS:IP 指向的存储单元

好了就这点,实验其实就是多试试,没啥别的

你可能感兴趣的:(汇编)