码迷,mamicode.com
首页 > 其他好文 > 详细

汇编--伪操作

时间:2016-02-08 21:21:36      阅读:312      评论:0      收藏:0      [点我收藏+]

标签:

汇编语言程序语句除指令以外还可以由伪操作(伪指令)和宏指令组成,这们可以完成如数据定义、分配存储区、指示程序结束等功能。

一、数据定义及存储器分配伪操作

这一类伪操作的格式是:
[Variable]  Mnemonic Operand,...,Operand[;Comments]
其中变量(Variable)字段是可有可无的,它用符号地址表示,其作用与指令语句前的标号相同,但它的后面不跟冒号.如果语句中有变量则汇编程序使其记以第一个字节的偏移地址.
    注释(Comments)字段用来说明该伪操作的功能,它也是可有可无的.
    助记符(Mnemonic)字段说明所用伪操作的助记符,常用的有以下几种:

  •     DB伪操作用来定义字节,其后的每个操作数都占有一个字节.
  •     DW伪操作用来定义,其后的每个操作数都占有一个字(低位字节在第一个字节地址中,高位字节在第二个字节地址中).
  •     DD伪操作用来定义双字,其后的每个操作数占有二个字.
  •     DQ伪操作用来定义四个字,其后的每个操作占有四个字.
  •     DT伪操作用来定义10字节(五个字),其后的每个操作数占有十个字节,形成压缩的BCD码.
VAR DB A, B
定义一个名为VAR的变量,VAR占用内存2个字节,并用ASCII 码 A 和 B 分别为这两个字节赋初值(初始化)。
变量名 DB 初始化列表
DATA DB 10, 20, 30, 40

 

 

 

表示 N的地址-VAR地地址,
VAR的地址数据: 5, 7, 19H, 23H, 0A0H,接着是N的地址.
用N的地址减VAR的地址,就是两个地址之间的字节数.
所以也就是以“字节”为单位的元素的个数




 操作数字段还可以使用复制操作符(duplication oprea)来复制某个tor操作数,例:

  ARRAY1    DB    2 DUP(0,1,2,?)
注1:使用PTR属性操作符,可以指定操作数的类型属性.
例: MOV    AX,WORD PTR OPER1


注2:使用LABEL伪操作可以使同一变量具有不同的类型属性.
例:
    BYTE_ARRAY    LABEL    BYTE
    WORD_ARRAY    DW    50 DUP(?)

二、表达式赋值伪操作EQU
格式:变量名    EQU    表达式
例:
    CONST   EQU    256            数赋以符号名
    DATA    EQU    HEIGHT+12      地址表达式赋以符号名
    ALPHA   EQU    7
    BETA    EQU    ALPHA-2      
    B       EQU    [BP+8]         变址引用赋以符号名B
    P8      EQU    DS:[BP+8]
    另有一个与EQU类似的=伪操作也可以作为赋值操作使用.这们之间的区别是EQU伪操作中的表达式名是不允许重复定义的,而=伪操作则允许重复定义.
例:
    EMP=7
    EMP=EMP+1


 

三、段定义伪操作

    存储器的物理地址是由段地址和偏移地址组合而成的,汇编程序在把源程序转换为目标程序时,必须确定标号和变量的偏移地址,并且需要把有关信息通过目标模块传送给连接程序,以便连接程序把不同的段和模块连接在一起形成一个可执行程序.为此,需要用到段定义伪操作,段定义伪操作的格式如下:

    segment_name    SEGMENT
            ...
    segment_name    ENDS

 


其中删节号部分,对于数据段、附加段和堆栈段来说,一般是存储单元的定义、分配等伪操作;对于代码段则是指令及伪操作。
    此外,还必须明确段和段寄存储器的关系,这可用ASSUME伪操作来实现,其格式为:

    ASSUME  assignment,...,assignment

 

其中assignment说明分配情况,其格式为:

    segment_register_name:segment_name

其中段寄存器名必须是CS、DS、ES和SS中的一个,而段名必须是由SEGMENT定义的段中的段名。而ASSUME NOTHING则可取消前面由ASSUME所指定的段寄存器。
    由于ASSUME伪操作只是指定某个段分配给哪一个段寄存器,它并不能把段地址装入段寄存器中,所以在代码段中,还必须把段地址装入相应的段寄存器中。但是,代码段不需要这样做,代码段的这一操作是在程序初始化时完成的。

    SEGMENT伪操作还可以增加类型及属性的说明,格式如下:

      segname    SEGMENT [align_type]
                         [combine_type]
                         [class]
                   ...
      segname     ENDS

一般情况下,这些说明可以不用.但是,如果需要用连接程序把本程序与其他程序模块相连接时,就需要使用这些说明.分别叙述如下:
.定位类型(align_type)可以是:


PARA   指定段的起始地址必须从小段边界开始,即段地址的最低的16进制数位必须为0.
BYTE   该段可以从任何地址开始
WORD   该段必须从字的边界开始,即段地址必须为偶数
PAGE   该段必须从页的边界开始,即段地址的最低两个16进制数位必须为0(该地址能被256整除)
.组合类型(combine_type)可以是:
PUBLIC 该段连接时将与有相同名字的其他分段连接在一起.其连接次序由连接命令指定.
COMMON 该段在连接时与其他同名分段有相同的起始地址,所以会产生覆盖.COMMON的连接长度是各分段中最大长度.
AT expression 使段的起始地址是表达式所计算出来的16位段地址.但它不能用来指定代码段.
STACK   指定该段在运行时为堆栈段的一部分.
MEMORY 指定该将分配在所有其他连接在一起的段的前面(在高地址上),如果连接时有几个指定MEMORY的段,则遇到的第一个段作为MEMORY段,其他段则作为COMMON段.
.类别(‘class‘) 连接时用于组成段组的名字.


 四、程序开始和结束伪操作

    在程序的开始可以用NAME或TITLE为模块取名字

    NAME module_name
汇编程序将以给出的module_name作为模块的名字.如果程序中没有NAME伪操作,则也可使用TITLE伪操作,其格式为:
    TITLE text
TITLE伪操作可指定每一页上打印的标题.同时,如果程序中没有使用NAME伪操作,则汇编程序将用text中的前六个字符作为模块名.text最多可以60个字符.如果程序既无NAME又无TITLE伪操作,则将用源程序文件名作为模块名.
    表示源程序结束的伪操作的格式为:
        END [label]
其中标号指示程序开始执行的起始地址.如果多个程序模块相连接,则只有主程序要使用标号,其他子程序模块则只用END而不必指定标号.


 五、对准伪操作

.EVEN伪操作使下一个字节地址成为偶数.一个字的地址最好从偶地址开始,所以对于字数组为保证其从偶地址开始,可以在它前面用EVEN伪操作来达到这一目的,例如:

DATA    SEGMENT
        ...
        EVEN
WORDAY  DW    100 DUP(?)
        ...
DATA    ENDS
.ORG Constant expression
如常数表达式的值为n,则ORG伪操作可以使下一个字节的地址为常数表达式的值n.
    地址计数器的值可以用$来表示,汇编语言允许用户直接用$来引用地址计数器的值,因此:
   ORG $+8
可以表示跳过8个字节的存储区.
    JMP $+2
可以表示一条空指令,该指令只是延迟处理机的一些时间,而无其他功能.


 六、基数控制伪操作

    汇编程序默认的数为十进制数,因而除非专门指定,汇编程序把程序中出现的数均看作十进制数,为此,当使用其他基数表示的常数时,需要专门以标记如下:
    .二进制数:由一串0、1组成其后跟以字母B,如00101100B
    .十进制数:由0~9的数字组成。一般情况下后面不必加上标记,在指定其他基数的情况下,后面可跟字节字母D,如178D。
    .十六进制数:由0~9及A~F组成的数,后面跟字母H。这个数的第一个字符必须是0~9,所以如果第一个字符是A~F时,应在其前加上数字0,如0FFFFH。
    .八进制数:由数字0~7组成的数,后面可跟字母O或Q,如1777Q。
    .RADIX伪操作,可以把默认的基数改变为2~16范围内的任何基数,其格式如下:
   .RADIX  expression
其中表达式用来表示基数值(用十进制表示)。
例如:
    MOV    BX,OFFH
    MOV    BX,178

    .RADIX 16
    MOV    BX,0FF
    MOV    BX,178D
是等价的。应当注意,在用.RADIX 16把基数定为十六进制后,十进制数后都应跟字母D。在这种情况下,如果某个十六进制数的末字符为D,则应在其后跟字母H,以免与十进制数发生混淆。
.字符串可以看成串常,可以用单引号或双引号把字符串放在其中,得到的是字符串的ACSII值,例如:‘ABCD’。
六、过程定义伪操作
格式为:
    procedure_name    PROC   Attribute
                       .
                     .
                       .
    procedure_name    ENDP
其中过程名为标识符,它又子程序入口的符号地址,它的写法与标号的写相同.属性(Attribute)是指类型属性,它可以是NEAR或FAR.段内调用使用NEAR属性,段间调用使用FAR属性


 表达式赋值伪指令

Expression_name EQU Expression 为等价伪指令   

LT1 EQU $-DATA_1 $表示LT1 EQU $-DATA_3 该条伪指令的地址(应该比数组大4个字节)

DATA_2 – DATA_1就是DATA_1数组起始地址与DATA_2数组起始地址的距离

 


地址计数器 $

MASM用$运算符返回当前程序语句的地址偏移值,利用该数值,我们可以计算出数组的长度。

$ 用在伪操作的参数字段时,和用在指令中的情况是不一样的。在指令中是不会变化的,始终表示本指令的首地址

而作为伪操作的参数字段时,$值是不段变化的。表示这里的此位置的偏移地址

ARRAY DW  1,2,$+4,5,6,$+4

此处两个$+4的值是不一样的。


ORG伪操作   用来设置当前 $ 的值。

ORG 4 为定位伪指令 指明一下开始定义的变量数组的起始地址从0004H开始

ORG $+8       可以表示跳过8个字节的存储区。亦即建立了一个8字节的未初始化的数据缓冲区。如果需要访问该缓冲区,则可用 label伪操作来定义该缓冲区的

BUFFER LABLE BYTE

ORG $ + 8

完成的功能和 BUFFER DB 8 DUP(?)  一样

 


  EVENT 伪操作

 使下一个变量或指令开始于偶数字节地址


 

 ALIGN 伪操作

ALIGN 伪操作 作为保证双字数组边界从4的倍数开始创造了条件。

作为保证双字数组边界4的倍数开始创造条件。

 align boundary  boundary 必须是2的幂。

 align  2  和 EVENT 作用一样  

 

 byData db 100 dup (0)

 意思就是定义100个byte型的空间, 里面的内容用()的数值填充, 如果()内是?, 表示不进行初始化

 


 基数控制伪操作

 汇编程序默认数为十进制数。

八进制 为  O 和 Q

.RADIX  expression  可以把默认的基数改变为2到16范围内的任何技术。

字符串可以看成串常量,可以用单引号和双引号引起来,得到的是字符串的ASCII值


 汇编语言程序格式

名字项

字母  A---Z

数字 0----9

专用字符  ?,@ - $

  


 操作项

  关系操作符

EQ   相等(equal)

NE  不等(not equal)

LT  小于(less)

GT  大于(greater)

LE  小于等于

GE  大于等于


 数值回送操作符

TYPE    回送该变量的以字节数表示的类型

LENGTH    对于变量中有DUP的情况,回送字节数,对于其他情况,回送1.

SIZE    回送字节数,但是此值是LENGTH*TYPE 的乘积

OFFSET    回送偏移地址

SEG(segment    回送变量或标号的段地址值。


1.过程定义伪指令(PROC/ENDP) proc 和 endp 相当于一个括号,里面是一个过程的代码。编译器通过这两个符号找到代码,进行处理。

格式:过程名 PROC 属性 
    技术分享

       RET
过程名 ENDP      就是结束一个子程序的意思。

 

 

 

 main proc far

far和near是子程序调用时的参数
如果子程序和调用程序在   一个段内,子程序参数设置为near
如果子程序和调用程序不在一个段内,子程序参数设置为far
这里主程序定义为far是因为:
系统把主程序当作DOS调用的一个子程序
DOS内核与主程序不是在同一个段地址内
所以主程序参数要用far

如果你的子程序和主程序在同一个代码段,则使用near,调用发生后,主程序堆栈中只压入ip值;
如果你的子程序和主程序不在一个代码段,则使用far, 调用发生后,主程序堆栈中将压入cs、ip值

一般说来,主过程一般是far属性。

汇编--伪操作

标签:

原文地址:http://www.cnblogs.com/zrui513/p/5103610.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!