汇编语言:第三章 寄存器(内存访问)

时间:2024-03-04 12:00:55

3.1内存中字的存储

CPU中寄存器是16位的,可以用高低字节存储一个字,但是每个内存单元是8位的,只能存储一个字节,

所以内存中用相邻2个内存单元存储一个字的高低字节

如:20000数值(4E20H)在地址0的内存单元数值为20H,在地址1的内存单元数值为4EH

  两个内存单元存储一个字型数据叫做一个字单元,

  字单元的起始地址为N就叫N地址字单元,表示一个字的低字节在地址N的内存单元,高字节在地址N+1的内存单元

  任意连续的2个内存单元都可以组成一个字单元

3.2 DS和 【address】

  CS寄存器用于存放下个指令所在内存单元的段地址。用jmp 1000:0 赋值 CS

  DS寄存器一般用于存放要访问的内存单元的段地址:

  如我们想把内存单元10000H(1000:0)的内容放到AL中:

  mov bx,1000H  将要访问的内存单元段地址放到bx中

  mov ds,bx    将bx放入ds段寄存器中

  mov al,[0]    将[0]代表的内存单元内容放到al中

  [0]: 表示一个内存单元,段地址是DS中的值,偏移地址是0,所以此时【0】表示1000:0内存单元的内容

  注意: mov ds,1000H是不行的,段寄存器是不可以直接赋值的,只能从其他寄存器转义到段寄存器

  相反:将AL写入10000H

  mov bx,1000H

  mov ds,bx

  mov [0],al

3.3字的传送

  mov指令两个参数的位数相同,

  当mov在寄存器与内存进行数据交互时,寄存器的字节数决定了传送单个内存单元还是字单元。

  mov ax,[0] 会将该地址的字单元数据组合成16位传入ax寄存器,即传送了一个字

  问题 :

  

  mov ax,1000H    ax=1000H

  mov ds,ax      ds=1000H

  mov ax,[0]      ax=1123H

  mov bx,[2]      bx=6622H

  mov cx,[1]      cx=2211H

  add bx,[1]      bx=8833H

  add cx,[2]      cx=8833H

3.4 mov,add,suv指令

  mov 寄存器,数据   数据只能转移到寄存器,不能转移到段寄存器

  寄存器,段寄存器,内存单元在mov指令中的位置都是可以随意换的

  mov 寄存器,数据

  mov 寄存器,寄存器

  mov 寄存器,内存单元

  mov 内存单元,寄存器

  mov 内存单元,段寄存器

  mov 段寄存器,内存单元

  mov 段寄存器,寄存器

  mov 寄存器,段寄存器

  

  add,sub只能对数据,寄存器,内存单元操作,不能用于段寄存器

3.5数据段:存放数据的连续内存单元形成一个数据段

  根据需要可以随意操作数据段中的数据

  如123B0H-123B9H是一个长度为10的数据段.

  1.累加前3个内存单元

  mov bx,123BH

  mov ds,bx

  add al,[0]

  add al,[1]

  add al,[2]

  2.累加前3个字型数据

  add ax,[0]

  add ax,[2]

  add ax,[4]

检测点3.1

  1)在Debug中用 \'d 0:0 1f\' 查看内存,结果如下

  0000:0000 70 80 F0 30  EF 60 30  E2-00 80 80 12 66 20 22 60

  0000:0010 62 26 E6 D6 CC 2E 3C 3B-AB BA 00 00 26 06 66 88

  下面程序执行前AX=0,BX=0 写出下列命令执行后相关寄存器中的值

  mox ax,1     AX=1

  mov ds,ax     DS=1

  mov ax,[0000]  AX=(16+0=10H)= 2662H

  mov bx,[0001]  BX=(16+1=11H)=E626H

  mov ax,bx    AX=E626H

  mov ax,[0000]  AX=2662H

  mov bx,[0002]  BX=(16+2=12H)=D6E6H

  add ax,bx     AX=FD48H

  add ax,[0004]  AX=2C14H  12C14

  mov ax,0     AX=0

  mov al,[0002]   AX=00E6H

  mov bx,0     BX=0

  mov bl,[000C]  BX=0026H

  add al,bl     AX=000CH

  2)内存情况如图所示:

  

  寄存器初始值: CS=2000H,IP=0,DS=1000H,AX=0,BX=0

    a.写出CPU执行顺序,及执行后相关寄存器值

      mov ax,6622H    ax=6622H

      jmp 0ff0:0100    

      mov ax,2000H    ax=2000H

      mov ds,ax      ds=2000H

      mov ax,[0008]    ax=C389

      mov ax,[0002]    ax=EA66

    

3.6栈

  后进先出LIFO,栈就是一个有特殊访问方式的存储空间

  只有2种操作,入栈和出栈,并且有个指针总是指向栈顶元素

3.7CPU提供的栈机制

  8086CPU提供PUSH和POP指令用于操作栈内存,PUSH和POP操作单位是字单元

  利用SS存储栈顶内存单元的段地址,SP存储栈顶内存单元的偏移地址.

  栈顶内存单元地址小,栈底内存单元地址大

  PUSH分两步: a.SP-2  b.写入/覆盖

  POP分两步  : a.读取     b.SP+2     内存单元的值依然存在,但是指针已经移到别处,再PUSH的时候就会覆盖原来值

3.8栈顶越界问题

  CPU不会指针是否指向栈顶或者栈低,只会根据SS:SP进行PUSH或者POP,需要程序员自己控制

  栈为空时SS:SP指向栈底内存单元的下一个内存单元

3.9 PUSH和POP指令

  PUSH和POP可以对寄存器、段寄存器、内存单元操作

3.10栈段

  把一段起始地址是16整数倍的连续的内存单元看做一个栈,就是一个栈段

  栈段根据SS:SP的指向利用PUSH、POP操作

段的综述数据段,段地址存放在DS中,add,sub,mov访问内存单元时候,CPU就把我们定义的数据段中的内容当做数据来操作

代码段,段地址存放在CS中,段中第一条指令的偏移地址存放在IP中,这样CPU就能执行我们的代码段

栈段   ,段地址存放在SS中,栈指针的偏移地址存放在SP中,CPU根据SS:SP进行PUSH,POP操作

 

检测点3.2

mov ax,1000H

mov ds,ax

mov bx,2000H

mov ss,bx

mov sp,10H

push [0]

push [2]

push [4]

push [6]

push [8]

push [A]

push [C]

push [E]

2)补全下面的程序,使得10000H-1000FH逆向复制到20000H-2000FH中

mov ax,2000H

mov ds,ax

mov ax,1000H

mov ss,ax

mov sp,0H

pop [E]

pop [C]

pop [A]

pop [8]

pop [6]

pop [4]

pop [2]

pop [0]