汇编学习记录之六

版权声明:转载请注明出处 https://blog.csdn.net/wjintao/article/details/84339939

资料来源:汇编语言第二版-王爽

1.源程序例子:

assume cs:codesg
codesg segment
start : mov ax, 0123H
        mov bx, 0456H
        add ax, bx
        add ax, ax

        mov ax, 4C00H
        int 21H

codesg ends
end start

在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令。

2.汇编指令

汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为CPU所执行。

例如:mov、add、sub等指令

3.伪指令

伪指令没有对应的机器码,不被CPU所执行,它是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。

上面的例子中出现了三种伪指令:

(3.1)segment指令和ends指令

segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须使用到的一对伪指令。

segment和ends的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。一个段必须有一个名称来标识,使用格式为:

段名 segment
        :
        :
        :
段名 ends

 比如上述例子中的:

codesg segment    ;定义一个段,段的名称为"codesg",这个段从此开始。
        :
codesg ends       ;名称为"codesg"的段到此结束

一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或者当作栈空间来使用。

前面学习的段的概念,在汇编源程序中得到了应用与体现,一个源程序中所有将被计算机所处理的信息:指令、数据、栈,被划分到了不同的段中。

一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。

从上述例子中我们可以看到,在codesg segment和codesg ends之间写的汇编指令是这个段中存放的内容,这是一个代码段。

(3.2)end 指令

end是一个汇编程序的结束标记,编译器在编译汇编源程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。所以,在我们写程序的时候,如果程序写完了,要在结尾处加上伪指令end。否则,编译器在编译源程序时,无法知道程序在何处结束。

注意,还要搞混了end和ends,ends是和segment成对使用的,标记一个段的结束,ends的含义可以理解为"end segment"。

我们在这里讲的end的作用是标记整个程序的结束。

(3.3)assume 指令

这条伪指令的含义是"假设",它假设某一段寄存器和程序中的某一个用"segment ··· ends"定义的段相关联。

通过assume说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相关联。

assume并不是一条非要深入理解不可的伪指令,我们编程时记着用assume将有特定用途的段和相关的寄存器关联起来即可。

比如,在上述例子中,我们用codesg segment ··· codesg ends定义了一个名为codesg的段,在这个段中我们存放代码,所以这个段是一个代码段。我们在程序的开头,用assume cs:codesg将用作代码段的段codesg和CPU中的段寄存器cs联系起来。

4.源程序中的"程序"

我们可以将源程序文件中的所有内容称为源程序,将源程序中最终由计算机执行、处理的指令或数据,称为程序。程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中。

5.标号

汇编源程序中,除了汇编指令和伪指令外,还有一些标号,比如"codesg"。一个标号指代了一个地址。比如codesg在segment前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段地址。

6.程序的结构

汇编源程序是由一些段构成的。我们可以在这些段中存放代码、数据或者将某个段当作栈空间来使用。

例如:

assume cs:code, ds:data, ss:stack
        ;定义"code"标号与代码段寄存器cs相关联
        ;定义"data"标号与数据段寄存器ds相关联
        ;定义"stack"标号与栈段寄存器ss相关联
data segment
    dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H
    ;在数据段中定义相关数据
data ends

stack segment
    dw 0, 0, 0, 0, 0, 0, 0, 0
    ;在栈段中定义栈段空间大小
stack ends

code segment
    ;在代码段中编写汇编指令完成程序运行逻辑
start:    mov ax, stack
          mov ss, ax        ;设置栈段寄存器ss指向stack段
          mov sp, 16        ;设置栈顶指针ss:sp指向stack:16位置
          mov ax, data
          mov ds, ax        ;设置数据段寄存器ds指向data段
          mov bx, 0         ;设置ds:bx指向data段中的第一个单元
          push ds:[bx]      ;将ds:[bx]中的内容入栈
          pop ds:[bx]       ;从栈中取出数据送入ds:[bx]指向的内存单元

          mov ax, 4C00H
          int 21H
code ends

end start
;在程序末尾添加end指令结束程序编译

上述例子中分别定义了数据段、栈段和代码段的标号,并且与相应的段寄存器相关联,然后在程序开始后,先设置了栈段寄存器ss、栈顶指针sp和数据段寄存器ds,最后在程序结尾处添加了end指令。

这只是一个非常简陋的例子,没有任何功能,只是演示了一个汇编源程序的布局结构而已。

有错误请指正,谢谢!    

猜你喜欢

转载自blog.csdn.net/wjintao/article/details/84339939