汇编语言

时间:2024-04-04 13:17:14

寄存器(内存访问):

字单元:储存一个字型数据的单元,一个字型数据有16位,由两个连续的内存单元组成。字型数据也分为高位字节和低位字节。一般将字单元的起始地址作为字单元的名称。如n地址字单元。

DS寄存器以及字的传送:

我们可以用命令直接将一个内存单元中的内容送入到一个寄存器中,只需要给出那个内存单元的偏移地址。如:mov al,[0]

但是这样只给出了偏移地址,没有段地址。这里就要说到寄存器DS。当我们像上面那样操作时,CPU会自动把DS中的数据作为段地址。然后根据我们提供的偏移地址,找到那个内存单元,把里面的数据存入我们指定的寄存器中。注意:我们上面给的寄存器为al,这是一个八位的,所以我们用上面那个方法时,CPU也只会那个指定的内存单元中的数据。而如果我们写的是ax,CPU会将那个当成字型数据来处理,传送给ax的是一个16位的数据,是我们指定的那个内存单元以及下一个内存单元中的内容。

我们同样也可以把寄存器中的数据根据地址传入内存,如mov [0],ax  道理和上面一样。同理,指令add和指令sub也可以这样做。

汇编语言

汇编语言

栈:

 

栈其实也类似于一个数据段,只是它遵循一个先进后出,或者说后进先出的规则。类似于一个箱子,最上面的数据成为栈顶,最下面的成为栈底。我们可以划出一段内存,作为我们的栈,同样首地址也得是16的倍数。这个栈是空的,里面还没有存入数据,然后我们可以用指令push来向里面存入数据,如push ax  这便是将寄存器ax中的值压入了栈的最底部,但是,CPU是如何知道要将ax中的数据压到我们规定的那个栈的最底部的呢?这里我们又要用到两个寄存器,段寄存器 SS 和寄存器 SP 。这两个寄存器类似于CS和IP。SS中也是存放段地址,SP中也是存放偏移地址。当我们使用指令push时,CPU会将数据存入SS:IP指向的地址中,但要注意的是,在栈的运算中都是以字为单位的,也就是16位二进制数,两个内存单元。

所以使用指令push时,是这样的:

push指令,SP先减2,然后CPU再把数据压入SS:SP指向的那个字单元,SS:SP指向的是那个字单元的低位字节,也就是那个低位字节所代表的内存单元的地址。

所以如果我们要向一段空栈里面用push指令存入数据的话,我们可以把SP设置为栈底的偏移地址再加一。这样,当用push时,SP先减2,然后正好指向栈底的第一个字的地址。

还有一个是出栈的指令:POP。它也是根据SS:SP指向的地址来把数据输出栈的。但是它与push不同的是,它先把数据输出,然后再SP加2。用POP输出栈里面的数据后,这些数据在栈中就不存在了,但是在内存中还是存在。这是一个有点抽象的概念,就是说,用POP弹出数据后,如果修改SP再指向刚刚那个字单元的地址,对于栈来说,那里是已经没有数据了的·,但是在内存中,这些数据并没有出去,我们还可以用其他方法来使用这些数据。

汇编语言

汇编语言

我们划了一个栈段,从10000到10010。然后设置一些基本设置。

 这样后,我们一直摁 t 就可以执行命令了。

汇编语言

汇编语言

 汇编语言

汇编语言

我们可以看到最后ax,bx中的数据互换了,遵循了先进后出的原则。

push,pop指令后面接的也可以是寄存器,或者内存的偏移地址([...])。

指令E,A,U,D这种需要指定段地址的,段地址都可以用段寄存器来代替,此时表示的段地址就为段寄存器中的值。

Debug中执行修改寄存器ss中的 t 命令的下一条命令也会接着立刻执行。

源程序:

  • 伪指令和汇编指令。源程序中有这两种指令,前者不被CPU执行,由编译器来执行。后者可以直接由计算机翻译成机器码然后执行。伪指令:segment和 ends是一对伪指令,要一起用,这一对指令定义了一个段,segment标志着开始ends标志着结束。而还有一个伪指令end标志着整个程序的结束。一个段还必须要有一个名称,写在segment的前面。汇编语言 比如这样的。段里面写的都是汇编指令。最上面的伪指令assume是假设的意思,它假设某一segment.....ends段和某一段寄存器连起来。用法如上图。源程序包括汇编指令和伪指令,我们将里面的汇编指令成为程序。
  • 标号。比如我们给段起的名字,这个名字最终将被编译,连接,成为这个段的地址。
  • 程序返回。程序p2在可执行文件中,它要想被执行,就得先有一个p1程序把p2从可执行文件中加载进内存,然后把CPU的控制权交给p2,p2执行完后,再把控制权交给p1。  将CPU交还给使它得以运行的程序就是程序返回。程序返回由两条代码实现。汇编语言                                                                                                                                                                                     

一个程序的诞生:

  1.  编写程序,可以文本编辑器,只要最终是纯文本文件就行。
  2. 连接,这里要用两个程序,一个汇编语言编译程序,一个连接程序。我们编写完源程序后,用汇编语言编译程序编译源程序生成目标文件,然后再用连接程序连接生成可执行文件。可执行文件可直接在操作系统中运行。
  3. 执行可执行文件

编译:

我们先用文本编辑器编写一个源程序:

汇编语言

扩展名改为.asm

我们在这里需要用到微软的masm5.0汇编语言编译软件。先到网上下载一个,照常解压安装。然后我们再打开DOSBox,找到我们下载的文件所在目录,然后进入masm模式

汇编语言

然后就出现了这样的。这里提示我们输入要编译的源文件名,源文件名默认为.asm扩展名,如果我们的文件的扩展名就是.asm那么就不用输入后缀名,如果不是就要输入完整的文件名。如果文件就在当前目录下,我们不用指明路径,如果不在,就要指明完整路径。

汇编语言

这里出现了新的一行,提示我们输入目标文件的名称,里面还给出了默认名称。如果我们直接摁enter,它就会在当前目录下生成这个默认名称的目标文件。当然我们还可以指定生成目标文件的路径。输入路径再输入我们的文件名,不用加后缀就可以了。

这里我们用它默认的。

汇编语言

这两个是在编译过程中产生的中间文件,我们不用管,然后再摁enter,结果:汇编语言

 出现错误了。

百度一下,有两种原因。一个是文件夹隐藏了后缀,也就是说你的完整的文件名可能是masm.asm.txt,我们可以把隐藏的选项去掉,然后再改一下文件名。还有一个就是在DOSBox中,只有MOUUNT过的盘才存在,所以可以看到我上面输的明明是D:\下面却成了C:\  

所以嫌麻烦的话,直接把文件放到masm的目录下就行了,改正之后就是这样子的:

汇编语言

这里有两行说明,这里说明有0个错误,如果出现其中一种错误,我们都将得不到最后的目标文件。

连接:

我们上面已经将源程序编译得到了.obj目标文件,然后我们要进行连接得到.exe可执行文件。这里我们要用到MASM文件中的link程序,我们进入link程序:

汇编语言

显示了一些信息,提示我们输入要连接的文件名。默认文件扩展名为.obj  规则和上面一样。

汇编语言

也是一直摁enter就可以了,倒数第二行那个是我们这个文件连接的库文件,如果我们这个文件中的源程序有调用库文件里的某些子程序的话,我们就要把这个文件和我们的文件连接起来。因为这里我们没有调用,所以直接跳过。

然后下面说我们没有设置栈段,这里可以不理会这个错误。

汇编语言

但是却出现了这种错误,百度也没查到结果。然后自己看来看去,发现在当前目录下也有一个可执行文件叫masm,所以我把生成可执行文件的名字改了一下,可以了。

汇编语言

 这样就好了,然后就可以运行我们的程序了。

汇编语言

但是,似乎....什么都没有发生....

但其实程序是运行了的,只是不会在显示屏上输出。

不过我们可以追踪我们的程序运行,在这之前,我们要先了解一些知识:

前面说到,我们要运行这个成绩,就要还有一个程序把我们这个程序加载进CPU,然后在我们这个程序运行完后,CPU的控制权交换给那个把我们程序加载进去的程序。那么,在DOSBox中,那个程序就是DOSBox的命令解释器,也是一个程序,叫command.com 

当我们要执行一个程序,我们在DOSBox界面输入文件名,然后command根据文件名找到可执行文件,然后把它加载进内存,command设置CS:IP指向程序入口,command暂定运行,CPU运行程序,程序运行完后,CPU控制权返回command。

我们可以用Debug来把程序加载进内存,但是Debug并不放弃对CPU的控制权。所以我们可以用它来追踪程序的运行。

这里又要了解一些DOSBox中程序加载的过程:

汇编语言

所以程序的物理地址为:

汇编语言

然后我们可以用指令   debug 文件名,来运行并追踪程序:

汇编语言

 我们用 r 指令和 u 指令查看寄存器和内存中的内容,这时CS:IP已经指向了我们的程序入口,并且一直到076A:000A都是我们的程序。一共有12个字节长,CX中存放的数据就是我们的程序长度。然后我们用 t 命令来让CPU执行命令。

汇编语言

 我们到最后要执行 INT 21 时用了指令 p ,执行这个就要用指令p。

注意:我们执行完程序后,CPU控制权是返还给了Debug,我们要再使用 q 命令CPU控制权才返回给command。

我们创建目标文件和可执行文件其实都可以用简便方法:

汇编语言

 直接在masm或link后面加上我们要编译或者要连接的文件路径以及名字就可以了。