汇编(123456)总结

        作为一名自学计算机的学生,由于对计算机的底层原理非常感兴趣,所以找来了王爽老师的汇编语言来学习。感觉王爽老师的这本书真的是特别的基础,很适合学编程的像我这样的新人去看,仅以此篇博客作为学习中的经验。

        纯正新手。。。有不对或不全面的地方求大佬轻喷

第一章 基础知识

        第一章是本书的基础,通过学习基本了解了寄存器、机器语言、汇编语言的含义。
        由于基础比较差,又特地在网上学习了二进制、四进制、十进制和十六进制之间的换算方法。二进制、四进制、十六进制转化为十进制的方法都是一样的,而十进制转化为其他进制的方法,通用的是短除法。

        这里就不作详细说明,因为在电脑上不好打出来==

        同时,为了学习汇编,又在电脑上安装了虚拟器VMware Workstation,以及PC2000的镜像。因为WIN10的系统没找到进入DEBUG的方法,且书中所用的系统为Windows2000,使用同样的环境更加方便学习。

        第一章的内容是比较简单的,个人觉得理解一下就成,问题不是很大。

第二章 寄存器

        第二章首先讲解了AX,BX,CX,DX四个寄存器,以及字节和字在寄存器中的存储方法,这些的理解在以后的学习中都会用到,所以一定要充分的进行理解。

        接着讲解了一些简单的汇编指令。

        再接着,是汇编中非常重要的内容,段地址和偏移地址的概念,此处需要熟练掌握。

        再接着,是CS/IP的学习,以及修改寄存器的六个基础指令:

                R命令:查看、修改CPU寄存器的内容;

                D命令:查看内存中的内容;

                E命令:改写内存中的内容;

                U命令:将内存中的机器指令翻译成汇编指令;

                T命令:执行一条机器指令;

                A命令:以汇编指令的格式在内存中写入一条机器指令。

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

        前两章都是前些日子学习的了,因此没有刚学习的时候经验感悟那么多了,第三章是刚刚学习的,经验和感悟会相对多一些。

        首先是字的存储,要搞清楚一个字分为两个字节,且字节存储时,高位内存单元存放高位字节,低位内存单位存放低位字节,在平时要能分清字单元和地址单元的区别。

        在读写内存单元的时候,要用到的DS段寄存器,和[0]形式的偏移地址,用来提取内存单元中的数据(注意DS需要用其它寄存器进行存入)8086CPU不支持将数据直接送入段寄存器的操作。(ss、ds等都不支持)

        MOV、ADD、SUB指令的内容。

        栈的概念和机制:push和pop,出栈和入栈时CPU的运行机理,IP的变化情况。(push:SP=SP-2,录入数据;pop:读取数据,SP=SP+2)push ax:将ax中的数据入库;pop ax:将出库的数据放置到ax中。

        其后的几小节多为加深理解的内容。理解这东西吧,因人而异,而且也很难系统的进行解释说明。

        写几个学习过程中自己发现的点吧:ffff大小为64KB;CPU执行修改SS后的下一个指令会被自动执行

第四章 第一个程序

        第四章中教会了我们制作我们的第一个汇编程序。

4.1 首先我们可以来一个总结,一个汇编程序从写出到执行的全部过程,如下(汇编程序需要使用masm和link程序进行编译和连接,在CSDN中可以找到这两个程):

        编程(Edit/TXT)——1.asm/1.txt——编译(masm)——1.obj——连接(link)——1.exe——加载(command)——内存中的程序——运行(CPU)

        我们先写出一个汇编程序的基本构成:

        assume cs:codesg             #将cs与codesg连接

        codesg segment               #程序开始

                (内容)                    #有一个缩进,其中使用汇编语言编写内容

                mov ax,4c00h

                int 21h                      #程序返回

        codesg ends                     #程序结束

        end                                   #结束

伪指令:

segment和ends是一对成对出现的伪指令,用来定义一个段;

assume表示“假设”,它假设某一段寄存器和程序中的某一个用segment和ends定义的段相关联;

end是一个汇编程序的结束标记。

codesg将被编译、连接程序处理为一个段的段地址。

4.2 编译中产生的列表文件(NUL.lst)和交叉引用文件(NUL.crf),以及连接中所产生的的印象文件(NUL.MAP),是不用理会的;而子程序(.LIB),由于在这里没有调用任何子程序,所以也不用理会。

#简单来说

NUL.xxx的不用理会直接ENTER

  .xxx的可以进行命名,如果格式不同(asm和txt),需要把格式也写上

4.3 简化进行编译和连接时

masm  C:\1.txt;    #格式不同,加上txt;若位置不是默认的和MASM在一个文件夹,加上位置;注意分号

link 1;                     #obj文件,格式可省略;位置和LINK在一个文件夹,位置省略;注意分号

4.4 在DOS中,shell为command,由它对其他程序进行加载,运行程序时COMMAND会放弃对CPU的控制权;而DEBUG不会放弃控制权。

#使用DEBUG时注意:(1)在cmd页面中打出debug 1.exe的方法使用,而不是先进入DEBUG,再使用(我的这样会出BUG,不知道是个例还是都这样);

                                  (2)cx中存放的为程序的长度;

                                (3)内存在运行程序时,会创建一个PSP数据区,长度为256个字节,100H,用来与被加载程序进行通信;

                                   (4)因此,程序的地址为SA(DS中的数据)+10h:0;PSP的地址为SA:0

                                  (5)执行到int 21h时,使用P指令,出现Program terminated normally字样;运行后使用Q指令退出debug;

                                   (6)PSP的头两个字节为CD 20

附一篇  寄存器中CS,DS,SS,ES的区别(个人总感觉学这个的时候容易弄混)

首先 cpu中寄存器用于存储内存中数据的物理地址

cs 为代码段寄存器,一般用于存放代码;

 通常和IP 使用用于处理下一条执行的代码

cs:IP

基地址:偏移地址

cs地址对应的数据 相当于c语言中的代码语句

ds 为数据段寄存器,一般用于存放数据;

ds地址对应的数据 相当于c语言中的全局变量

ss 为栈段寄存器,一般作为栈使用 和sp搭档;

ss地址对应的数据 相当于c语言中的局部变量

ss相当于堆栈段的首地址  sp相当于堆栈段的偏移地址

es 为扩展段寄存器; 

第五章 [BX]和loop指令

5.1

        [BX]表示一个内存单元,它的偏移地址在bx中,段地址在ds中。

        loop表示循环,它的基本用法为:

                mov cx,循环次数

        s:      循环执行的程序段

                loop s

5.2

       (1)之所以有[BX]的存在,是因为在汇编源程序中,mov ax,[0]  会被编译为  mov ax,0。因此,我们需要BX对其进行中转。

        inc bx     #含义为bx的内容加1

        (2)loop指令的格式是:loop标号,CPU执行loop指令的时候,要进行两步操作,a:(cx)=(cx)-1,b:判断cx中的值,不为零则转至标号s处执行程序,如果为0则向下执行。

        #在汇编源程序中,数据不能以字母开头,所以要在前面加0.比如,9138h在汇编源程序中可以直接写为“9138h”,而A000h在汇编源程序中要写为“0A000h”

        #其实loop在debug中执行时,先自动执行(cx)=(cx)-1,然后对cx进行判定,不为0就跳转IP为标号处的IP,原理是很简单的。

        #当程序的前面部分的运行情况我们不需要了解时,可以使用g 指令跳转,如g 0012h表示执行程序到当前代码段(段地址在CS中)的0012h处。

        #当需要循环的次数过多时,可使用P指令。其用法为,再遇到loop指令时,使用P指令,debug会自动重复循环中的指令,直到(cx)=0为止。

        也可以直接使用g指令跳转,更为简单粗暴。

5.3 Debug和汇编编译器masm对指令的不同处理

在Debug中,

mov ax,[0]

表示将ds:0处的数据送入ax中;

但是在汇编源程序中,指令“mov ax,[0]”被编译器当做指令“mov ax,0”处理

Debug会将[idata]解释为一个内存单元;而编译器则将其解释为“idata”

若要在汇编源程序中也使用[idata],则要在[]前加上段寄存器。如ds:[0]

5.4 loop指令和[bx]和联合使用是我们最应该了解的,书上有详细解说,在这里不作介绍。

#“ds:”“cs:”“ss:”“es:”,在汇编中我们称为段前缀。

#在一般的PC机中,0:200——0:2ff的256个字节一般是空的。

            实验四提示:(1)CS/code在这里都可以代表程序的开始

                                (2)程序的长度在CX中,mov ax,4c00h  int 21h的长度为5

第六章 包含多个段的程序

dw:定义字形数据 。

start:用来表示开始运行代码的地方,和end start 配合使用      #这样看来,用其他字符也是可以的;专门设定一个开始的地方,是因为dw后的数据不需要被执行,如果被执行了反而会出错,所以干脆设定一个开始的地方。

在代码中使用栈时,可以用dw直接定义数据为0的空间,之后将这段空间作为栈使用。设置ss和sp即可。

为了表示的清晰,我们往往将数据、栈和代码放到不同的空间,这时,我们可以用 assume cs:code,ds:data,ss:stack这样的方法;使用时直接如mov ax,data使用即可,data在这里只是个地址。

注:mov ds,data是错误的,因为data会被编译器处理成一个表示段地址的数值。

CPU将哪里作为指令执行,只跟end 后跟的如start 有关,与assume中如何设定的无关。

如果一个段中的数据占n个字节,则程序加载后,该段实际占有的空间为(n/16+1)*16    /为取整。

开始时ds ss等都会是程序开始处的地址值,只有当执行了mov ss,mov ds后才会变为程序中需要的值。

db:定义单字节数据

 

猜你喜欢

转载自blog.csdn.net/qq_42631643/article/details/80949933