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


    3.1内存中字的存储

    一个字 = 2个字节。由于内存单元是字节单元(一个单元存放一个字节),存放字需要两个连续的内存单元,这个字的低位字节放在低地址单元,高位字节放在高地址单元

    3.2 DS和[address] 对内存单元的读写

    8086CPU中,内存地址由段地址和偏移地址组成,DS寄存器存放要访问的数据的段地址。如果将DS设置为1000H,不能直接 mov ds,1000H,  而是:mov ax,1000H   mov ds,ax 。(8086CPU不支持直接将数据(立即数)送入段寄存器的操作)

    问题3.2 

    将al中的数据送入内存单元10000H中。

    mov bx,1000H

    mov ds,bx

    mov [0],al   ;;al低8位字节,所以送入8bit数据。操作的数据的长短跟据使用的寄存器的大小确定

    sub和add等运算操作符不能操作段寄存器

    检测点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 68

    下面的程序执行前,AX=0,BX=0,写出每条汇编指令执行完成后相关寄存器中的值

    mov ax,1

    mov ds,ax

    mov ax,[0000]  AX= 8070H  <---x ds设置为了0001,所以全部错了。。。     ---> 2662

    mov bx,[0001]  BX= F080H  <---x                       E626

    mov ax,bx      AX= F080H  <---x                            E626

    mov ax,[0000]  AX= 8070H  <---x                       2662

    mov bx,[0002]  BX= 30F0H  <---x                       D6E6

    add ax,bx    AX= B160H  <---x                      FD48

    add ax,[0004]   AX= 124FH  <---x                      2C14

    mov ax,0    AX= 0000H  <---x                        0000

    mov al,[0002]  AX= 00F0H  <---x                        00E6

    mov bx,0      BX= 0000H  <---x                         0000

    mov bl,[000C]   BX= 0066H  <---x                       0026

    add al,bl    AX= 0156H  <---x                      010C取低地址数据  000C

    (2)内存中的情况如图,各寄存器的初始值: CS= 2000H, IP= 0, DS= 1000H, AX= 0, BX= 0;

    .写出CPU执行的指令序列(用汇编指令写出)

    .写出CPU执行每条指令后,CS,IP和相关寄存器中的值

    .数据和代码在内存中有区别吗?如何确定内存中哪些信息是数据,哪些是程序?

                                              CS=2000H,  IP=0,  DS=1000H,  AX=0,  BX=0

         mov ax,6622H              指令执行前:CS=2000H,  IP=3,  DS=1000H,  AX=0,  BX=0   执行后:CS=2000H,  IP=3,  DS=1000H,  AX=6622H,  BX=0

         jmp 0ff0:0100                指令执行前:CS=2000H,  IP=8, DS=1000H, AX=6622H, BX=0      执行后:CS=0ff0H,  IP=0100H,  DS=1000H,  AX=6622H,  BX=0 等价于CS=1000H, IP=0

      mov ax,2000H               指令执行前:CS=1000H, IP=3,  DS=1000H, AX=6622H, BX=0      执行后:CS=1000H,  IP=3,  DS=1000H,  AX=2000H,  BX=0

      mov ds,ax           指令执行前:CS=1000H, IP=5,  DS=1000H, AX=2000H, BX=0      执行后:CS=1000H,  IP=5,  DS=2000H,  AX=2000H,  BX=0

      mov ax,[0008]               指令执行前:CS= 1000H, IP=8, DS=2000H, AX=2000H, BX=0         执行后:CS=1000H,  IP=8,  DS=2000H,  AX=0C389H,  BX=0

      mov ax,[0002]     指令执行前:CS=1000H, IP=0B, DS=2000H, AX=0C389H, BX=0         执行后:CS=1000H,  IP=0B,  DS=2000H,  AX=0EA66H,  BX=0

    程序根据CS:IP和DS:偏移地址 来确定内存中的信息是指令还是数据。

    jmp 段地址:偏移地址    -》mov cs,段地址    mov ip,偏移地址

    jmp ax     -》mov ip,ax(不是说真有这条指令,是指功能类似这样)

    3.6 栈

    一种具有特殊访问方式的存储空间LIFO:数据遵循先进后出的规则

    问题3.6

    如果将10000H~1000FH这段空间当作栈,初始状态栈是空的,此时,SS=1000H,SP=?

    push数据时,sp = sp - 2,所以栈是由高地址到低地址。栈为空时,栈顶指针指向栈空间的最高地址的下一个单元

    栈的最高地址为SS=1000, IP=000F,所以栈顶的下一个单元为0010,IP=0010

    3.7 CPU提供的栈机制

    8086CPU提供入栈和出栈的指令,最基本的两个指令是PUSH(如栈),POP(出栈),8086CPU的入栈和出栈都是以字(2byte)为单位进行

    CPU怎么知道栈顶位置-》任意时刻,SS:SP 指向栈顶元素

    数据入栈(push)时 SP=SP - 2,出栈(pop)时 SP=SP + 2; TIPS:栈有大小(最大=2的16次方个字节,CPU在内存上操作的最小单元为字节byte),8086CPU中栈的大小范围:0~64KB(地址连续,起始地址为16的倍数的内存单元),栈顶的最大变化范围:0~FFFFH。8086CPU不保证栈的超界问题,由程序员自己确定。

    问题3.7

    编程 将10000H~1000FH这段空间当作栈,初始状态栈是空的,将AX,BX,DS中的数据入栈。

    mov cx,1000H

    mov ss,cx  ;设置栈的段地址

    mov sp,0010H ;设置栈的偏移地址

    push ax

    push bx

    push ds

    问题3.8

    编程:

    (1) 将10000H~1000FH这段空间当作栈,初始状态栈是空的;

    (2) 设置AX=001AH,BX=001BH;

    (3) 将AX,BX中的数据入栈;

    (4) 然后将AX,BX清零;

    (5) 从栈中恢复AX,BX原来的内容

    mov ax,1000H

    mov ss,ax    ;设置栈的段地址

    mov sp,0010H ;设置栈顶

    mov ax,001AH

    mov bx,001BH

    push ax

    push bx

    mov ax,0   ;sub ax,ax     用sub更好,sub指令的机器码为2个字节,mov为3个字节

    mov bx,0

    pop bx

    pop ax 

    问题3.9

    编程:

    (1)将10000H~1000FH这段空间当作栈,初始状态栈是空的

    (2)设置AX=001AH,BX=001BH

    (3)利用栈,交换AX和BX中的数据

    mov ax,1000H

    mov ss,ax   ;设置栈的段地址

    mov sp,0010H   ;设置栈顶

    mov ax,001AH

    mov bx,001BH

    push ax

    push bx

    pop ax

    pop bx

    问题3.10

    如果要在10000H处写入字型数据,可以用以下的代码完成:

    mov ax,1000H

    mov ds,ax

    mov ax,2266H

    mov [0],ax

    补全下面的代码,使它能够完成同样的功能:

    要求:不能使用"mov 内存单元,寄存器"这类指令

    mov ax,1000H

    mov ss,ax

    mov sp,2           ;将1000:0当作栈,10002作栈顶

    mov ax,2266H

    push ax   ;入栈 先将sp-2,使得ss:sp指向新的内存单元,然后再将数据送入ss:sp指向的新的栈顶单元。记住栈的地址是由高到低的。入栈或出栈操作的内存单元都是sp指向的内存单元,所以出栈时,先将数据取出,再sp+2

    问题3.11

    如果将10000H~1FFFFH这段空间当作栈段,初始状态栈是空的,此时,SS=1000H,sp=?

    sp=0000H

    检测点3.2

    (1)补全下面的程序,使其可以将10000H~1000FH中的8个字,逆序复制到20000H~2000FH中。(以字为单位复制)

    mov ax,1000H

    mov ds,ax

    mov bx,2000H

    mov ss,bx

    mov sp,0010H

    push [0]

    push [2]

    push [4]

    push [6]

    push [8]

    push [A]

    push [C]

    push [E] 

    (2)补全下面的程序,使其可以将10000H~1000FH中的8个字,逆序复制到20000H~2000FH中

    mov ax,2000H

    mov ds,ax

    mov bx,1000H

    mov ss,bx

    mov sp,0010H

    pop [E]

    pop [C]

    pop [A]

    pop [8]

    pop [6]

    pop [4]

    pop [2]

    pop [0]

    实验2 用机器指令和汇编指令编程

    2.实验任务

    (1)使用Debug将下面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。

    FFFF:0000处的数据

     

    mov ax,ffff

    mov ds,ax    ;设置数据段地址

    mov ax,2200

    mov ss,ax  

    mov sp,0100  ;设置栈段

    mov ax,[0]    ;ax=C0EA

    add ax,[2]     ;ax=C0FC

    mov bx,[4]    ;bx=30F0

    add bx[6]      ;bx=6021

    push ax        ;sp=00FE,修改的内存单元的地址是 2200:00FE和2200:00FF 对应地址的内容为FC C0

    push bx   ;sp=00FC,修改的内存单元的地址是 2200:00FC和2200:00FD 对应的地址的内容为21 60

    pop ax    ;sp=00FE,ax=6021

    pop bx    ;sp=0100,bx=C0FC

    push [4]  ;sp=00FE,修改的内存单元的地址是 2200:00FE和2200:00FF 内容为 F0 30

    push [6]  ;sp=00FC ,修改的内存单元的地址是 2200:00FD和2200:00FC 内容为 31 2F

    (2)分析为什么2000:0~2000:f中的内容会发生改变?

    初始没有执行这段代码时,我们使用d命令观察2000:00内存,都是00,怎么创建栈结构指向这段内存时,我们发现有些数据了。这些数据是什么?

           我们发现这里面有cs值、ip值、ax值(这个容易看出来),还有bp值(00 00),还有flag的值(这个我用肉眼是看不出来了。呵呵,就是那个一排英文字符)。

           为什么,在讲内中断这章时,你就明白了。t命令实际是引发了单步中断,执行中断例程时,CPU会将一些中断例程使用的的寄存器变量自动压栈到栈中,此例中就包括了上述的寄存器变量的值。

           我们可以不必理会这些寄存器的变量,我们只关心sp就可以了。有它指示,我们就可以对栈进行操作了。而此时的sp是正确的,

           注意:这个栈和我们创建的栈是同一个栈结构(为什么,ss=2000H了),由于t命令必须保存寄存器变量的值(这个是中断程序定义的。)它也占用一定的空间。可能我们定义的栈空间比较小;频繁的使用push指令,为了避免栈顶超界,我们尽量使栈空间大些,就像此程序,设定栈空间是100H。 此问题答案copy自:https://www.cnblogs.com/Base-Of-Practice/articles/6883882.html

  • 相关阅读:
    程序员修炼之道读书笔记02
    程序员修炼之道读书笔记01
    2021年1月30日 体温上报app03(百度API的获取和配置方法)
    2021年1月28日 体温上报app02
    2021年1月27日 体温上报app01
    2021年1月26日 sqlite数据库
    2021年1月25日 列表与适配器
    16.CSS margin用法
    14.CSS 块级元素与行内元素
    12.CSS 简单认识margin
  • 原文地址:https://www.cnblogs.com/linxisuo/p/13177133.html
Copyright © 2020-2023  润新知