zoukankan      html  css  js  c++  java
  • 【我希望我能鼓起勇气】汇编语言

    寄存器和存储器的区别?

    寄存器、存储器、内存的区别

      从范围来看,它们所指的范畴不一样。

      寄存器是中央处理器内的组成部份。它跟CPU有关。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。

      存储器范围最大,它几乎涵盖了所有关于存储的范畴。寄存器,内存,都是存储器里面的一种。凡是有存储能力的硬件,都可以称之为存储器,这是自然,硬盘更加明显了,它归入外存储器行列,由此可见——。

      内存就是专业名上的内存储器,它不是个什么神秘的东西,它也只是存储器中的沧海一粟,它包涵的范围也很大,一般分为只读存储器和随即存储器,以及最强悍的高速缓冲存储器(CACHE),只读存储器应用广泛,它通常是一块在硬件上集成的可读芯片,作用是识别与控制硬件,它的特点是只可读取,不能写入。随机存储器的特点是可读可写,断电后一切数据都消失,我们所说的内存条就是指它了。

      CACHE是在CPU中速度非常块,而容量却很小的一种存储器,它是计算机存储器中最强悍的存储器。由于技术限制,容量很难提升,一般都不过兆。

     即 寄存器:CPU中可以存储数据的器件      存储器:范围很广

    寄存器和存储器的区别

      存储器在CPU外,一般指硬盘,U盘等可以在切断电源后保存资料的设备,容量一般比较大,缺点是读写速度都很慢,普通的机械硬盘读写速度一般是50MB/S左右。内存和寄存器就是为了解决存储器读写速度慢而产生的多级存储机制,从20世纪50年代开始,磁芯存储器曾一度成为主存的主要存储介质,但从20世纪70年代开始,逐步被半导体存储器所取代,目前的计算机都是用半导体存储器。现在的DDR2内存的读写速度一般为6~8GB/S,跟机器性能也有关系。一般1Bit由六MOS管构成

      而寄存器(又称缓存)一般是指由基本的RS触发器结构衍生出来的D触发,就是一些与非门构成的结构,一般整合在CPU内,其读写速度跟CPU的运行速度基本匹配,但因为性能优越,所以造价昂贵,一般好的CPU也就只有几MB的2级缓存,1级缓存更小。使用寄存器可以缩短至零长度、节省存储空间,提高指令的执行速度。不同的寄存器有不同的作用,如:通用寄存器(GR)用以存放操作数、操作数的地址或中间结果;指令寄存器(IR)用以存放当前正在执行的指令,以便在指令执行的过程中,控制完成一条指令的全部功能。

      CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。最理想的情况就是CPU所有的数据都能从寄存器里读到,这样读写速度就快,如果寄存器里没有要用的数据,就要从内存甚至硬盘里面读,那样读写数据占的时间就比CPU运算的时间还多的多。所以评价一款CPU的性能除了频率,缓存也是很重要的指标。

      从根本上讲,寄存器与RAM的物理结构不一样。 一般寄存器是指由基本的RS触发器结构衍生出来的D触发, 就是一些与非门构成的结构,这个在数电里面大家都看过; 而RAM则有自己的工艺,一般1Bit由六MOS管构成。所以, 这两者的物理结构不一样也导致了两者的性能不同。寄存器 访问速度快,但是所占面积大。而RAM相反,所占面积小, 功率低,可以做成大容量存储器,但访问速度相对慢一点。

      1、寄存器存在于CPU中,速度很快,数目有限;存储器就是内存,速度稍慢,但数量很大;计算机做运算时,必须将数据读入寄存器才能运算。

      2、存储器包括寄存器,存储器有ROM和RAM两类,寄存器只是用来暂时存储,是临时分配出来的,断电后,里面的内容就没了

    已知寻址能力,求总线宽度

    1个CPU的寻址能力为8KB,那么它的地址总线的宽度为(?) 

    寻址能力容易产生迷惑,是指可以索引到的数据量, 每个存储单元可以存储1Byte的数据,寻址能力8KB说明一共有8*1024个存储单元

    (每个存储单元存储8bit的数据), 10根总线可以寻址长度是2*10=1024个存储单元,那么 8*1024个存储单元的总线宽度为13

    【其实就是2*x=8x1024】

     

    从内存中读取1024字节的数据,8086至少读多少次?80386至少读多少次?

    8086 80386的数据总线宽度分别是16根、32根

    8086有16根数据总线,每次能够读取16位的数据, 16位 = 2字节,所以1024字节要至少读取512次

     

    assume:段寄存器的说明语句;

      在汇编语言源程序中可以定义多个段,每个段都要与一个段寄存器建立一种对应关系。建立这种对应关系的说明语句格式如下:

      ASSUME  段寄存器名:段名[,段寄存器名:段名, ……]

      其中:段寄存器是CS、DS、ES、SS、FS和GS,段名是在段定义语句说明时的段名。

      在一条ASSUME语句中可建立多组段寄存器与段之间的关系,每种对应关系要用逗号分隔。例如,

      ASSUME  CS:CODE1, DS:DATA1

      上面的语句说明了:CS对应于代码段CODE1,DS对应于数据段DATA1。

      注意:代码段寄存器不能由程序员在源程序中对其赋值,其值是由操作系统在装入它进入系统运行时自动赋值的。

    寄存器总结:https://blog.csdn.net/baidu_39511645/article/details/78368112

    检测点9.1【转移指令的原理】

      https://blog.csdn.net/e891377/article/details/93728567  

    https://blog.csdn.net/Sino_Crazy_Snail/article/details/79118488#%E6%A3%80%E6%B5%8B%E7%82%B991-1

    1)程序如下。

    assume cs:code
    data segment
       ?
    data ends
    
    code segment
      start: mov ax,dtat
             mov ds,ax
             mov bx,0
             jmp word ptr [bx+1]
    code ends
    end start

    若要使jmp指令执行后,CS:IP指向程序的第一条指令,在data段中应该定义哪些数据?

    (2)补全程序,使得jmp指令执行后,CS:IP指向第一条指令

    assume cs:code
     
    data segment
        dd 12345678H
    data ends
     
    code segment
        start:
            mov ax, data
            mov ds, ax
            mov bx, 0
            mov [bx], __
            mov [bx+2], __
            jmp dword ptr ds:[0]
     
    code ends
    end start

    db,dw,dd的区别

    db定义字节类型变量,一个字节数据占1个字节单元,读完一个,偏移量加1
    dw定义字类型变量,一个字数据占2个字节单元,读完一个,偏移量加2
    dd定义双字类型变量,一个双字数据占4个字节单元,读完一个,偏移量加4

    检测点9.2

     

     

     检测点9.3

     补全编程,利用loop指令,实现在内存2000H段中查找第一个值为0的字节,找到后,将它的偏移地址存储在dx中。

    assume cs:code
    
    code segment
    
    start:  mov ax,2000h
    
            mov ds,ax
    
            mov bx,0
    
          s:mov cl,[bx]
    
            mov ch,0
    
            ——————   
    
            inc bx
    
            loop s
    
         ok:dec bx
    
            mov dx,bx
    
            mov ax,4c00h
    
            int 21h
    
    code ends
    
    end start

    答案inc cx ; 因为loop的尿性,执行loop s时,首先要将(cx)减1。“loop 标号”相当于dec cx  if((cx)≠0) jmp short 标号【先减再做判断】

     检测点10.4

    下面的程序执行后,ax中的数值为多少?

    内存地址   机器码        汇编指令       执行后情况
    
    1000:0     b8 06 00      mov ax,6       ax=6,ip指向1000:3
    
    1000:3     ff d0         call ax        pop ip,ip指向1000:6
    
    1000:5     40            inc ax
    
    1000:6     58            mov bp,sp      bp=sp=fffeh
    
                             add ax,[bp]    ax=[6+ds:(fffeh)]=6+5=0bh

    sp值fffeh 【看的网上 不保证】

    冷静了一下再看 发现完全不用管sp也就是地址是啥 只要知道在这个地址 【即栈顶】 这个数是啥就可以【刚刚入栈的IP值】

      因为call ax就是跳转到地址为6的地方,并且ip入栈,ip这时候是5,也就是跳到第四行,ax还是6,加上栈顶数5

    ----------------------------------------
    程序分析:
    1. 遇到CALL指令,老样子,(ip)(此时是5),压栈;这里我们可以不管sp是多少(我的debug是0000H),目前我们确定的就是IP的值是5(压栈的数据)。
    此时栈中有一个字就是0005H。(sp)=(sp)-2 =>>0000H-2=fffeH 2.由于是CALL ax,(ax)=0006H,直接转移到1000:0006处执行,将sp的值赋值给bp。 3.由于bp默认隶属于ss段寄存器,故[bp]指向ss段的物理内存,也就是栈结构的空间,此时栈中就一个字0005H,那么(ss:[bp])=0005H(读取ss栈中的内容)。 4.add ax,[bp] ,0006H+0005H=000BH 5.结果:ax的值是000BH。inc ax指令依然没有执行。
    --------------------------------------
    (bp)=(sp)
    bp 默认使用的 SS 作为段地址
    [bp] 等价于 SS:[bp],现在指向 栈顶
    
    add ax,[bp] 取出 栈顶内容0005H 与 (ax) 相加
    
    AX      0006H
    [bp]    0005H
    ----------------
            000BH
    
    十进制的 十一
    十六进制的 B

    检测点10.5

    此时 DS==SS,ds:[0eH == ss:[0eh] 正好就是栈顶, 而栈顶正好存着 【IP旧】

     

    自己也能想出来  就是想说这个的思路更清楚一点    可看可不看的
    ----------------------------------------------------
    offset s
    取出 标号s 所在的 偏移地址,这里假设为 X
    
    mov word ptr ss:[0], offset s
    等价于
       (ss:[0]) = X
    
    ss 指向 data 段 
    在data段的 00-01 内存单元放入 【偏移地址  X】
    ---------------------------------------------------------
    在 data段的02-03内存单元放入【CS的值】
    ---------------------------------------------------------
    call dword ptr ss:[0]
    等价于
    push CS
    push IP
    jmp dword ptr ss:[0]
    
    将  CS  压入栈,也就是存放到   0EH-0FH  内存单元
    将  IP  压入栈,也就是存放到  0CH-0DH  内存单元
    此时的IP 已经完成自动增加,IP的值为Y,是nop语句的偏移地址
    
    执行 jmp 指令,又等价于设置新的CS和IP值,再跳转到CS:IP
    (IP)= SS:[0] = X  低地址是偏移地址
    (CS)= SS:[02] = CS 高地址是段地址
    相当于,段地址一直没有变过,IP值现在为X,CS:IP指向 标号s
    -----------------------------------------------------------------
    mov ax,offset s
        ax的值变为 X (标号s的偏移地址)
    
    sub ax,ss:[0ch]
        ss:[0cH] 存着 Y (nop语句的偏移地址)
        sub 是减法指令
        X-Y 本质就是 nop 语句所占用的内存单元个数
        nop语句只占用1个内存单元
        X-Y的值为 1,即0001H
    AX的值最终为 0001H
    
    mov bx,CS  
        bx的值变成 CS
    sub ss:[0eH]
        ss:[0eH] 存着 CS
        CS自己减去自己当然等于0,即0000H
    BX的值最终为 0000H
    ---------------------------------------------------------------------
    AX 的值为 0001 H   BX 的值为 0000 H

     

    检测点13.1

     

    (1)8000H~7FFFH 即(-32768~32767)

    答案:最大转移位移是指的相对地址的偏移量,它用十进制表示比较好。

           如果从loop的指令角度上看,loop就是个段内短转移,它的范围是-128~127,也就是说最大转移位移是128.

           如果从例程中bx变量来说,先搞定bx存储二进制补码数据的表示范围。对于16位来说它表示的范围是(-32768~32767)。

           我们知道在内存中是按照计算机补码方式存储的,最小的负数(也就是绝对值最大的数)是8000H也就是-32768,那么它最大的转移位移是32767。

           注:别考虑(bx)=32768-offset s这种情况了,因为offset 是有可能是0.

           有人说是FFFFH,它在内存中存储,如果表示的是数值,那么它的值是:-1

    jp:push bp
    mov bp,sp
    add [bp+2],bx ;中断例程
    pop bp
    iret
    jpend:nop
    ;为啥中断程序一定至少要有两个标号【lp-lpend】是为了后面程序安装的时候,cx
    的值是程序代码的长度的。

     

  • 相关阅读:
    Linux编译工具:gcc入门
    Socket编程实践(3) 多连接服务器实现与简单P2P聊天程序例程
    Socket编程实践(2) Socket API 与 简单例程
    Socket编程实践(1) 基本概念
    数据结构图文解析之:二分查找及与其相关的几个问题解析
    数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现
    [CG编程] 基本光照模型的实现与拓展以及常见光照模型解析
    郑重声明!本博客内容皆为原创且首发于博客园
    【原创】面试官:谈谈你对mysql联合索引的认识?
    【原创】为什么Mongodb索引用B树,而Mysql用B+树?
  • 原文地址:https://www.cnblogs.com/yundong333/p/12789925.html
Copyright © 2011-2022 走看看