前言
王爽老师的书的P77也对伪指令进行了说明,可以参照着一起阅读本文。
什么是伪指令?
伪指令(Pseudo Instruction)是用于对汇编过程进行控制的指令,该类指令并不是可执行指令,没有机器代码,只用于汇编过程中为汇编程序提供汇编信息。例如,提供如下信息:哪些是指令、哪些是数据及数据的字长、程序的起始地址和结束地址等。伪指令有2个特点:
(1)由于是伪“指令”,因而它只存在于汇编语言中。高级语言中不叫指令,叫语句;
(2)由于是“伪”指令,也即“假”指令,因而不是可执行指令,不会产生机器代码,不会占用ROM空间,只用于汇编过程中为汇编程序提供汇编信息。
以上内容摘自百度百科。
在上面这个程序中,一直到assume都是伪指令。
再看一个更简单的程序
这里我们更清楚地说明一下
codesg segment
codesg ends
(codesg是段的名字)
是一对成对使用的伪指令,也是写汇编程序时必须要用到的一对伪指令。
因为一个有意义的汇编程序中至少要有一个段。
segment和ends的作用是定义一个段,segment说明一个段开始,ends说明一个段结束。
注意区分end和ends
end也是一个伪指令,是一个汇编程序的结束标记。而ends标志着一个段的结束,可以把ends理解成”end segment“
再插播一个对这段代码的解释
段的最后两句是什么意思?其实就是固定格式啦
无需知道这两句话是什么意思,怎么运作的。只需要知道在程序的末尾使用这两条指令就可以实现程序返回,通常这两句指令是加在数据段的末尾,就像上面的例子一样。
(程序返回的意思就是把CPU的控制权从自己手里交出去,因为运行你写的程序的时候CPU的控制权是在你写的这个程序手里的)
一些常用的伪指令
ASSUME
assume用来说明各段的功能。
它假设某一段寄存器和程序中的某一个用segment……ends定义的段相关连,我们通过assume来说明这种关联。
assume不需要太深入的理解,只需要知道
assume是将有特定用途的段和相关的段寄存器关联起来。
比如我们定义一个段叫abc
abc segment
……
abc ends
如果abc被当成代码段来用,那么就要把abc和cs联系起来
assume cs:abc
关于assume有一个很重要的问题
参考博文汇编assume伪指令
也就是说,如果你在汇编开头说了
assume ds:data
那么代码段中也要有
mov ax,data
mov ds,ax
这两句在有多个段的程序中是必不可少的(也就是说基本上在所有的汇编程序里都要有,王爽老师的书前半部分没有,是因为一开始要讲的简单点)
那么这两句话是什么意思呢?有什么作用呢?(P132)
它们用来告诉CPU,写程序的人定义的这个段是代码段,那个段是数据段。
我们为数据段起名叫data,代码段起名叫code,堆栈段叫stack。但是英文单词只对人有意义,机器又看不懂,因此机器不会因为
code segment
code ends
就知道你定义的这个段是代码段了。
在程序的开头,我们会写上
assume cs:code,ds:data,ss:stack
这些是assume伪指令,伪指令是由编译器执行的,也就是仅仅存在于源程序中的信息,CPU并不知道它们。
如果要CPU按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令是CPU要执行的内容。
我们在源程序的最后用end start指明了程序的入口,这个入口将被写入可执行文件的描述信息,可执行文件中的程序被加载如内存中后,CPU的CS:IP被设置成指向这个入口从而开始执行程序中的第一条指令。标号start在code段中,这样CPU就将code段中的内容当成指令来执行了。
在code段中,start之后,需要用
mov ax,stack
mov ss,ax
和
mov ax,data
mov ds,ax
必要的时候,可以是
mov ax,stack
mov ss,ax
mov sp,20H
和
mov ax,data
mov ds,ax
mov bx,0
这样,ss:sp指向stack:20;ds:bx指向data段中的第一个单元。
就我目前看来,code段是不用这样mov标明的,就像上面说的,end start已经告诉CPU了,CPU也已经把start后面的东西当成代码来执行了,所以就不用再费事了。
assume一般放在程序的最前面。
segment……ends
segment……ends是一对成对使用的伪指令,也是写汇编程序时必须要用到的一对伪指令,因为一个有意义的汇编程序中至少要有一个段。
segment和ends的作用是定义一个段,segment说明一个段开始,ends说明一个段结束。
end
end是一个伪指令,是一个汇编程序的结束标记。