查漏

  • 2^n-1
  • word=2B=16bit
  • 8086CPU在内部用两个16位地址合成的方法形成一个20位的物理地址

    • 物理地址=段地址x16(16进制的情况下左移一位,2进制左移四位)+偏移地址
    • 一个段的最大长度为64KB。2^16
    • 段地址:偏移地址
  • 内存没有分段,段的划分来自CPU,只是一种管理方式

    段寄存器(提供段地址)

  • 8086CPU:CS(指令) DS SS ES

  • CS:代码段寄存器 IP:指令指针寄存器
    • CPU刚开始工作: CS=FFFFH IP=0000H
    • CS:IP -> 读取指令
      • IP=IP+读取指令的长度
    • 修改CS、IP的内容(不能用mov)
      • jmp CS’:IP’
      • jmp ax (用ax里的值修改IP)
  • DS:数据段寄存器 [address]:数据段偏移地址

    • 例子:读取1000:0中的数据(一个内存单元8bit,如果只传递一个字节用al存就够了)
      • mov bx,1000H
      • mov ds,bx ;一定要通过通用寄存器把值赋给段寄存器
      • mov al,[0] ;al8位
      • mov [0],al;寄存器->内存单元
      • mov ax,[0];将字型数据送入ax
      • mov [0],ax
  • SS:存放栈顶的段地址 SP:存放栈顶的偏移地址

    • 任何时刻SS:SP执行栈顶元素
      • push ax;SP=SP-2,ax->新SS:SP
    • 栈:从高地址->低地址
    • 栈空时,SP指向栈的最高地址的下一个单元(SP-2)
      • mov ax,1000H
      • mov ss,ax
      • mov sp,0010H ;初始指向最高地址的下一个单元

image.png

  • 栈顶越界危险
  • push和pop只对SP操作
    • push:SP-2
    • pop:SP+2
  • push和pop可以对段寄存器进行操作
    • push [0] (ds:0)
    • pop es

代码段(数据段、代码段、栈段)

  • 16位系统:起始地址为16的倍数,大小<=64KB
  • CPU只认CS:IP指向的内存单元

实验

  • R:查看寄存器内容
    • 查看:-r
    • 修改:-r ax
  • D:查看内存
    • -d fff0:0 ff(查看fff00000开始的ff个内存单元的内容)
  • E:改写内存(用机器指令)
    • -e b810:0 01 01 02 02..
  • U:机器指令->汇编指令
  • T:执行机器指令
  • A:以汇编指令的格式在内存写入一条机器指令(常用)
    • -a CS:IP(输入的起始地址)
  • P:
    • 执行中断:int xx
    • 跳过循环
  • G

    • g 指令地址:直接跳到指定的指令地址继续执行
  • 清零:xor ax,ax

内存中字的存储

  • 一个内存单元存储一个字节
    • 1个内存单元的长度是8bits,占一个字节。
    • 32位是指地址长度,四个字节。
    • 内存地址指向内存单元(可能1个或更多),32位系统每次读取的内存单元都是4个字节的偶数倍,可能会根据需要忽略多余的字节。
    • 寻址地址是根据你的CPU的地址总线来确定的,跟内存没多大关系。
    • 至于8字节的内存单元是认为定义,是为了兼容性和编程实现考虑的