找回密码
 立即注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

查看: 2269|回复: 2

汇编语言基础知识

[复制链接]
  • TA的每日心情
    开心
    2018-10-31 14:26
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    78

    主题

    109

    回帖

    1019

    积分

    高级会员

    积分
    1019

    猴年

    龙龙实名认证 发表于 2015-6-22 02:58:38 | 显示全部楼层 |阅读模式
      
      一、概述
      汇编程序把源代码转换成用二进制代码表示的目标代表,也就是obj文件;再通过链接程序把目标文件与库文件及其他目标文件一起链接在一起形成可执行文件(exe文件)。汇编语言源程序通用性差,一般不具有可移植性。与高级语言相比,汇编语言编写的程序结构十分紧凑,运行速度很快,可以最大限度地发挥计算机硬件的性能。汇编程序与目标程序、可执行程序之间的关系如图一:
      

      图一 汇编程序与目标程序、可执行程序之间的关系
      二、汇编语言规范
      1.源程序由两种指令构成
      (1)汇编语句(指令语句)
      (2)伪指令(指示性语句)
      2.指令格式
      (1)指令语句的格式:
      标号:助记符 参数,...,参数;
      注释
      (2)指示性语句的格式:
      名字 命令 参数,...,参数;注释
      3.特点
      (1)指令语句被翻译成机器代码,诸如MOV、ADD等。
      (2)指示性语句不会被翻译成机器代码,它的作用是指导汇编程序运行时进行一些操作,例如定义符号,分配存储单元、初始化存储器等,指示性语句本身不占用存储单元。伪指令时在汇编程序对源程序汇编期间处理的操作。
      三、名词解释
      1.变量
      存放在存储单元的操作数是变量,它具有三种属性:
      (1)段属性(SEGMENT)
      存放变量的存储单元所在段的段地址。
      (2)偏移量属性(OFFSET)
      存放变量的存储单元地址与段的起始地址之间的偏移量。
      (3)类型属性(TYPE)
      变量有三种类型:字节(BYTE),字(WORD)和双字(DOUBLE WORD)。
      2.标号
      标号是对存放指令的存储单元地址所命名的名称。标号也有三种属性:段属性、偏移量属性、类型属性。
      标号的类型属性与变量不同,它的类型是NEAR或是FAR,默认为NEAR。
      标号可以作为JMP指令和CALL指令的目标操作数。
      四、两种指令的介绍
      (一)、汇编语句(指令语句)
      指令的介绍请见前一篇blog《80x86的指令系统(二)》http://blog.csdn.net/scucj/archive/2009/06/19/4281659.aspx
      (二)、伪指令(指示性语句)
      1.符号定义语句
      (1)等值语句 EQU
      格式:NAME EQU EXPRESSION
      功能:给符号定义一个值,或者定义为别的符号名,甚至可以定义为一条可以执行的指令。
      EQU语句在未解除前,不能重新定义。解除语句RUREG,用RUREG语句解除后的符号可以重新定义。
      另外等号语句=也与EQU语句类似,但是它能对符号进行再定义。
      例子:
      NEW_PORT EQU PORT_VAL
      RUREG NEW_PORT
      NEW_PORT EQU PORT_VAL + 10
      2.数据段定义语句
      数据段定义语句为一个数据项分配存储单元,用一个符号名与这个存储单元相联系。
      (1)DB (Define Byte)
      从指定单元开始,定义若干个字节的数据或ASCII码字符。
      举例:
      THING DB ?;定义一个字节
      THING是一个符号名,它与存储器中的一个字节相联系,即它是一个字节变量。
      ?表示为数据项分配相应的存储单元,但是不产生一个目标码初始化这些存储单元。
      (2)DW((Define Word)和DD(Define Double Word)
      DW定义从指定单元开始,定义如干个字的数据或ASCII码字符;DD则定义从指定单元开始,定义如干个双的数据或ASCII码字符;
      举例:
      BIG_THING DW 1234H
      12H和34H分别放在两个连续的字节单元中,34H放在低地址的字节中,12H放在高地址的字节中。
      (3)DUP
      它利用给出的一个初值或者一组初值,重复执行初始化存储单元。
      举例:
      DB 100 DUP(0);100个字节全初始化位0
      DW 10 DUP(?);保留10个字
      DB 10 DUP(10 DUP(0));10次重复的0的10次重复
      DB 5 DUP(1,2,4 DUP(3),2 DUP(1,0));定义了1,2,3,3,3,3,1,0,1,0的5份拷贝
      3.段定义语句
      8086是按段来组织程序和利用储存器。段定义的主要命令:SEGMENT、ENDS、ASSUME、ORG
      (1)对于SEGMENT、ENDS,段定义伪操作的格式如下:
      segment_name SEGMENT
      ...
      ...
      segment_name ENDS
      对于数据段、附加段和堆栈段来说,一般是对存储单元的定义、分配等伪操作,对于代码段,一般是指令。
      (2)对于ASSUME,用来明确段和段寄存器的关系,格式为:
      ASSUME assignment,..., assignment
      其中,assignment的格式为:
      segment register_name : segment register_name
      段寄存器必须为CS、DS、ES、SS、FS、GS中的一个,段名必须为程序中已定义的段名。
      (3)对于ORG,它规定了段内的起始地址,格式如下:
      ORG Expression
      此语句可以使下一个字节的地址称为常数表达式的值。例如:
      VECTORS SEGMENT
      ORG 10
      VECT1 DW 1234H
      则VECT1的偏移地址为0AH, 也就是十进制的10。
      4.过程定义语句
      过程是程序的一部分,可以被程序调用。调用过程指令为CALL,从过程返回的指令为RET。指令有两种情况:段内的和段间的。
      对于段内的,调用和返回指令只将段内的偏移地址入栈和出栈;对于段间的,则需要将段地址和段内偏移地址均入栈和出栈。
      过程定义语句的格式为:
      PROCEDURE_NAME PROC [NEAR]
      ...
      RET
      PROCEDURE_NAME ENDP
      或者
      PROCEDURE_NAME PROC FAR
      ...
      RET
      PROCEDURE_NAME ENDP
      调用过程时在CALL指令后写上被调用的过程名。RET指令总是放在过程体的末尾,用来返回主程序。当过程和主程在同一代码段时,过程可定义为NEAR属性;若不在一个代码段时,
      则过程定义为FAR属性。在主程序调用过程时,需要先设置入口参数,过程执行结束后将运行结果返回给主程序。主程序和过程的参数传递主要有四种[3]:
      (1)采用CPU内部寄存器传送参数。
      (2)当主程序与过程处于同在一个代码段时,过程可以直接访问该代码段中的变量。
      (3)通过地址表传送变量地址。将所有变量的偏移地址顺序存放在一张地址表中,然后通过寄存器将地址表的地址传送给过程,进入过程后可用寄存器间接寻址方式从地址表中取出
      变量地址,以便访问所需变量。
      (4)通过堆栈传送参数或参数地址。调用过程前在主程序中用PUSH指令将参数地址压入堆栈;进入过程后再用基址寄存器BP从堆栈中取出这些参数地址,并送入寄存器,以便寄存器
      以间接寻址方式访问所需变量。
      5.结束语句
      除了END以外,每一个结束语句与开始语句成对出现。比如, SEGMENT和ENDS,PROC和ENDP。
      END标志着整个源程序的结束,END语句的格式:
      END expression
      其中expression必须产生一个存储器地址的值,这个地址为程序执行时第一条执行指令的地址。举例:
      START:
      ...
      END START
      那么程序会从START处开始执行。
      五、汇编语言源程序的框架结构及基本程序设计[3]
      1.汇编语言源程序的框架结构
      标准化汇编语言源程序采用分段结构,包括代码段、数据段和堆栈段。任何一个源程序至少有一个代码段,用来放置指令性语句构成的程序。堆栈段和数据段根据实际要求来决定。数据段用来定义变量,定义所需要的数据常数及分配存储空间,中间都是由伪指令语句构成。堆栈段根据需要而设置,如果用户使用堆栈操作,最后使用用户自己定义的存储空间;若没有定义堆栈段,将自动使用系统定义的堆栈区。过程可放在代码段,也可单独建立一个过程段(另一个代码段)。EQU可放在数据段、代码段,宏指令一般放在程序的开始。PUBLIC可放在程序的任何一行。因为各逻辑段通过段寄存器寻址,所以必须在代码程序的开头给相应的段寄存器赋值(装入地址)。ASSUME伪指令仅仅是指明了各逻辑段与段寄存器的对应关系,即该逻辑段是什么属性的逻辑段,并没有对段寄存器赋值。因此,必须在程序的开头先进行.DS、SS、ES(若存在扩展段)的段基址装入。
      对于单模块程序的基本框架如下:
      NAME        模块名(可省略)
      EQU       符号定义区(可依据需要而定)
      EXTRN       外部符号名说明(依实际需要而定)
      PUBLIC      公共符号名说明(依实际需要而定)
      数据段名(如DATA)  SEGMENT 参数(依据实际要求而定,可省略)
      变量定义
      预置存储空间
      数据段名(如DATA) ENDS
      堆栈段名(如STACK)   SEGMENT 参数(依实际要求而定)
      预置堆栈空间
      堆栈段名(如STACK) ENDS
      代码段名(如CODE)  SEGMENT 参数(依实际需要而定)
      ASSUME:段寄存器指派
      START: MOV AX,DATA ;段地址装填
      MOV DS,AX
      MOV AX,STACK
      MOV SS,AX
      ……
      主程序体
      MOV AH,4CH
      INT 21H
      过程名1 PROC  类型说明
      过程体1
      过程名1 ENDP
      过程名2 PROC  类型说明
      过程体2
      过程名2 ENDP
      代码段名(如CODE) ENDS
      END START
      2.基本程序设计
      (1)简单顺序运行程序
      按照顺序执行的程序,没有分支、没有循环。
      (2)分支程序
      程序的分支主要是靠条件转移指令来实现的。
      (3)循环程序
      循环程序的设计主要用于某一段程序需要重复执行多次,主要使用循环指令LOOP、LOOPZ或LOOPNZ或条件转移指令。一个循环结构由以下几部分组成:
      1)循环体:需要重复执行的程序段部分。
      2)循环结束条件:在循环程序中必须给出循环结束条件,常见的循环比如有计数循环。
      3)循环初态:循环开始前的初始值的设置。
      (4)子程序
      子程序是一个独立的程序段,能完成某些确定的功能,并能被其它程序调用。
      六、其他
      1.地址计数器$
      在源程序中,使用地址计数器来保存当前正在使用的汇编指令的偏移地址。可以直接使用$引用地址计数器的值,表示本条指令的第一个字节的地址。例如:
      ARRAY DW 1, 2, $+4,
      假如ARRAY分配的偏移地址为0074,那么$+4的值为007C。
      2.处理器选择伪操作
      80X86的处理器都支持8086/8088指令系统,但更高级的处理器支持一些新的指令,所以需要告诉编译器程序使用哪一种处理器支持的指令集。这类伪操作主要有以下几种:
      .8086
      .286
      .286P
      .386
      .386P
      .486
      .486P
      .586
      .586P
      汇编程序默认值为.8086。
      3.存储模型与简化段定义伪操作
      (1)MODEL 伪操作
      格式:MODEL momory_model [, model options]
      功能:它用来指定内存模式,即说明在存储器中如果存放各个段。在Win32下,momory_model 只有FLAT模式。
      (2)简化的段定义伪操作
      .CODE [name]
      对于一个代码段的模型,段名为可选项
      对于多个代码段的模型,则需要为每个代码段指定段名
      .DATA
      .DATA ?
      .FARDATA [name]
      可指定段名。
      .FARDATA? [name]
      .CONST
      .STACK [size]
      可指定堆栈段大小,默认为1KB。
      4.属性操作符PTR
      格式:type PTR expression
      功能:给已分配的存储地址赋予另外一种属性,使得该地址具有另外一种类型。type表示被赋予新的类型属性,expression则表示符号地址。type可以是 BYTE(字节)、WORD(字)、
      DWORD(双字)、FAR(段间)和NEAR(段内),expression可以是变量和标号(其中BYTE,WORD和DWORD用于变量,FAR和NEAR用于标号)。PTR不会给新定义的变量或标号分配存储单元。
      举例:
      TWOB DW ?
      ONEB DB ?
      TWOB 符号地址的类型属性为字,ONEB 符号地址的类型属性为字节。
      通过下面使用PTR操作符进行的定义:
      VARB EQU BYTE PTR TWOB
      VARW EQU WORD PTR ONEB
      VARB与TWOB两个符号地址具有相同的段地址及偏移地址,但它们的类型属性不同:TWOB的类型属性为字,而VARB的类型属性为字节。同样VARW和ONEB两符号地址具有相同的段地址
      及偏移地址,ONEB的类型属性是字节,而VARW的类型属性是字。
      从上面的例子可以看出,PTR可以用来临时的类型转换,相当于C语言中的强制类型转换。
      5.宏汇编和条件汇编[3]
      (1)宏汇编
      1)宏指令、宏定义、宏调用
      宏指令可由用户自己在源程序中定义。宏指令一经定义,便可在以后的程序中多次调用。
      宏定义的格式为:
      宏指令名 MACRO [实际参数]
      ...
      ENDM
      宏调用的格式为: 宏指令名 [实际参数]
      2)宏扩展。具有宏调用的源程序被汇编时,每个宏调用将被MASM进行宏展开。宏展开实际上是用宏定义时设计的宏体去代替相应的宏指令名,并且用实际参数一一取代形式参数。
      3)宏嵌套。宏定义中允许使用宏调用,但所调用的宏指令必须先定义过。而且宏定义中还可以包含宏定义。
      举例:为了实现ASCII码和BCD码之间的转换,需要把AL中的内容左移或右移四位,采用8086的指令实现如下:
      MOV CL, 4
      SAL AL, CL
      采用一条宏指令代替,宏定义如下:
      SHIFT MACRO
      MOV CL, 4
      SAL AL, CL
      ENDM
      以后需要将AL得内容左移4位,则只需要用一条指令:
      SHIFT
      注意:MACRO与ENDM必须成对出现。
      (2)条件汇编
      条件汇编是对给定的条件进行测试,汇编程序根据测试结果,将一段程序嵌入源程序汇编或不进行汇编,它的一般格式为:
      IF 条件 (表达式)
      (指令体1) ;条件为真汇编指令体1
      ELSE (指令体2) ;条件为假汇编指令体2
      ENDIF
      其中:IF…ENDIF;条件汇编伪指令助记符,必须成对出现,不可省略。
      6.简单汇编环境的搭建
      32位windows程序: masm32v9.0 or nasm + editplus2 + 一个资源编辑器

    想学,太烦了。。。

    看不懂 就回复顶一下吧

    说得灰常灰常 好啊`一定要大力支持啊`

    看不懂 太深奥

  • TA的每日心情
    无聊
    2017-10-8 15:10
  • 签到天数: 8 天

    [LV.3]偶尔看看II

    1

    主题

    106

    回帖

    261

    积分

    中级会员

    积分
    261
    besteast 发表于 2017-10-8 15:26:20 | 显示全部楼层
    充分的放松
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|虫虫联盟 ( 备案号:蜀ICP备15018121号-1 )

    GMT+8, 2024-3-29 01:51 , Processed in 0.374725 second(s), 26 queries .

    Powered by Discuz! X3.5 Licensed

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表