目录

伪指令

段定义

结束标记

段关联标记

数据定义

标号

offset指令

seg指令

地址标号

数据标号

代码分段

程序标识

多文件系统

字符输入

重复定义

注释

重复汇编伪指令

伪指令汇总


伪指令

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

示例1:一段汇编程序中的伪指令示例

PS1:伪指令在debug中直接执行汇编代码是不可用的,但若要将汇编程序交由编译器执行,则是必要的。

PS2:其中结尾处的mov ax,4c00h与int 21h对任何汇编程序都是必要的,作用是在程序结束之后,将CPU的控制权交还给使它得以运行的程序(常为DOS系统)。类似C语言编程结尾时的return 0;(详见汇编学习笔记——汇编指令的int与iret指令部分以及汇编学习笔记——设计与执行的中断部分与BIOS与DOS系统部分)

段定义

定义:一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使用。格式为:段名 segment 表示段的开始;段名 ends 表示段的结束。

示例:完整的汇编程序

PS1:一个有意义的汇编程序中至少要有一个段,这个段用来存放代码,如上图中的code segment 至 code ends 便是程序中的代码段

结束标记

定义:汇编程序的结束标记,用于在编译器编译程序时告知其汇编程序在哪结束。标记记为:end (注意和段定义中的ends区分)

示例:完整的汇编程序

PS:一个可被编译器解读的汇编程序中必须包含end,如上图中的程序结尾处的end便是整个程序的结束标记。

段关联标记

定义:将CPU中的段寄存器与汇编程序中某一个用segment...ends定义的段进行关联的标记,格式:assume 段寄存器名:段名,段寄存器名:段名,...,段寄存器名:段名

示例:完整的汇编程序

PS:如上图中assume cs:code代表将名为code的程序段与代码段寄存器关联;ds:data代表将名为data的程序段与数据段寄存器关联;ss:stack代表将名为stack的程序段与栈段寄存器关联

数据定义

定义:可将程序中需要使用的常量提前定义于程序中,使用时通过代码段寄存器的段前缀(段前缀相关见汇编学习笔记——寻址与存储)直接调用。格式:dw idata,idata,...,idata 定义字型数据(define word);db idata,idata,...,idata 定义字节型数据(define byte);dd idata,idata,...,idata 定义双字型数据(define double-word)

示例1:编程计算0123H,0456H,0789H这三个数据的和,并将结果存入ax寄存器

PS1:如上图,用dw定义的三个字型数据将被存入cs:[0],cs:[2],cs:[4]指向的三块字单元中,可如第七行所示调用

PS2:如上图第八行,因每个字单元占用两个字节的的内存空间,因此偏移地址每次都必须+2

PS3:用以上方式定义数据时,会导致cs:[0]地址中的内容不再是代码而是数据,因此需要使用程序起始标号来指定代码区域的起始位置,避免系统错误的将数据解析为代码执行

示例2:通过定义空数据获取额外空间

PS:如上图所示,通过dw 0,0,....,0定义了一个32字节的数据空间,并将之作为临时的栈使用

标号

定义:写在某一代码段的,用于代表该段处的偏移地址的自定义字符串。常同各类跳转指令(如jmp/jcxz/loop)结合使用。

具体用法见以下offset指令、起始标号及汇编学习笔记——汇编指令的loop、jmp等部分

offset指令

定义:用于取得某标号的偏移地址的指令。格式:offset A 若A标号所在的偏移地址为000a,则offset A等价于立即数000a

示例1:使用offset获取代码段的偏移地址

PS1:如上图所示,代码中的offset start被编译为0000,而代码中的offset s被编译为0006,都与其在内存中存储的实际偏移地址相同

PS2:注意和段名区分,如以上代码中若加入mov ax,code,则代表将code代表的段地址存入ax,被编译后为mov ax,076A。offset与标号结合得到的是标号所在的偏移地址(相对与标号所在的代码段),而段名代表的是段地址

示例2:通过标号和offset结合,动态调节程序中的代码

PS1:如图1、2,在代码执行前,076b:001b段的代码仍为nop

PS2:如图3,在代码执行后,处于076b:0008处的代码被拷贝到076b:001b并占用了两个字节(覆盖了原本处于该处的两个nop)

seg指令

定义:用于取得某标号的段地址的指令。格式:seg A 若A标号所在的段地址为000a,则seg A等价于立即数000a

示例1:测试seg指令

PS:如上图所示,seg指令确实将code标号所代表的段地址取出

地址标号

定义:只可用于代码区域内的字符串标记,编译器将之解析为所处代码段位置的偏移地址,地址标号常用于标识代码段的起始位置或与loop/jmp等跳转指令结合使用。格式:A:

示例:使用标号指定代码开始处

PS1:如上图1第四行,使用begin:来标识代码段开始,并在第十三行使用end begin来标识代码段结尾,编译器通过end处填写的标号来寻找程序的入口。由此,程序将从代码段标识的位置开始执行。

PS2:如上图2,当程序被装载入系统时,IP中存储的偏移地址不再是0,而是起始标号所在的6(cs[0]~cs[5]都用于存储程序开头使用dw定义的三个数据)

PS3:如上图1,程序中使用loopy:标记一个程序段的位置,此后执行loop指令时通过loopy标号所代表的代码段内存地址进行程序跳转实现循环。

数据标号

定义:可用于代码区域和数据区域的字符串标记,编译器将之解析为所处代码段位置的地址(根据数据定义指令的类别决定是否包含段地址)的同时记录其所标记的数据的长度,数据标号常用于代表某段数据的起始位置。格式:A

示例1:在代码段中使用数据标号标识数据的起始位置

PS:如上图1所示,在调用a所标记的数据时,直接使用a[si],这样的代码在内存中的形态如图2所示,为cs:[si+0000]即cs:[si+offset a]。而b标号的使用同样验证了这一点,由此可知数据标号可用于简化数据操作。当调用数据时不再需要计算其与内存中的所在的偏移地址,甚至不需要考虑其段地址。

示例2:基于示例1的代码,数据标号存储其所标记数据的长度体现

PS:基于示例1的代码,a标记的是字节型数据,而b标记的是字型数据,因此如上图所示,在对a/b标号进行操作时,指令会自动适应其数据长度进行更改,如mov b,2会自动转换为mov word ptr cs:[b],2。而inc b则会每次为b增加一个字单元(相当于add b,2)

示例3:在代码段之外使用数据标号

PS:如上图所示,可用数据标号标记定义在数据段中的数据,其功能不会因在代码段之外而失效,相对的地址标号则无法在代码段之外使用

示例4:标号嵌套标记

PS1:如上图所示,可将数据标号作为数据进行定义,若将之作为字类型数据进行定义,则其代表标号的偏移地址。若将之作为双字类型数据进行定义,则其代表高位字存储段地址,低位字存储便宜地址的数据。

PS2:若将数据标号视为C语言中的指针,则标号嵌套使用代表的便是指向指针的指针

代码分段

定义:当程序中需要使用数据、栈时,将数据定义与栈空间分配的部分分配至不同的代码段中,提高程序的可读性

示例:实现数据0001H,0010H,0100H的出入栈以及累加

PS1:如上图1第4、9行,将数据定义与栈定义分配至不同的段

PS2:如上图1第17行起至第21行,除了代码段寄存器之外,其他的段寄存器在使用之前都需初始化,并且在已完成数据与栈的段定义之后,可直接用段名获取其段地址

PS3:如上图2所示,程序完成了其预定功能

程序标识

定义:使用proc同endp指令显性的标识一段代码为程序,提高可读性的同时作为多文件组织的基础

示例:提高可读性的指令

PS:比照高级程序设计语言中子程序的结构,可在程序的开头加上程序名(地址标号)接proc作为一段子程序开始的标志,并在结尾用程序名接endp作为一段子程序结束的标志(注意,程序中的ret返回指令仍是不可缺少的)。这样的结构达成的效果同单独使用一个地址标号标识子程序的开始达成的效果是一样的,但可区别与仅用于程序内jmp/loop等指令使用的地址标号,由此提高程序的可读性。在主程序中调用子程序时同样适用call 子程序名 的形式。

多文件系统

定义:使用extrn与public两种指令链接两个文件中的代码,实现将不同类别不同功能的代码拆分的目的。

示例:将主程序同子程序分为两个文件

PS:如上,将两个文件分别编译后链接到一起,而后直接通过主程序作为入口调用

字符输入

定义:在汇编程序中,用单引号将数据框起的方式指名数据是以字符的形式给出,编译器将把它们转化为相对应的ASCII码再交予计算机执行。格式:'idata'

示例:改变字符的大小写

PS1:如上图2,通过将字符用单引号框起,其以ASCII码的形式被存储,大小写分明

PS2:如上图1,同将字符与11011111进行与操作,可将字符转为大写;通过将字符与00100000进行或操作,可将字符转为小写。如上图2,程序执行完之后,两个单词的大小写都完美转换了

重复定义

定义:当定义数据时需要重复定义相同的数据时使用。格式:db 重复的次数 dup(重复的字节型数据);d2 重复的次数 dup(重复的字型数据);dd 重复的次数 dup(重复的双字型数据);

示例1:功能示例表

示例2:代码实测

PS:如上图所示,定义的数据都完整的在内存中展示出来了,用此种方法可以相对简介明了的定义栈、数组等结构

注释

定义:既不被CPU执行也不被编译器执行的字符,写在程序用用于标识、提示,只对程序编写人员可见的提高程序可读性的字符。格式:;注释内容

示例:完整的汇编程序

PS:如上图中的‘;设置栈段’便是一条注释,编写程序时可以自行添加任意的字符内容,只需要在作为注释的字符内容前加上分号:‘;’,该字符就不会被CPU和编译器识别。

重复汇编伪指令

定义:用于连续产生完全相同或基本相同的一组代码的伪指令

示例1:重复伪指令rept

PS:如上图所示,rept指令类似高级语言中for的功能,指定重复次数后多次拷贝指令段。但其实现实际上类似宏,将重复同一指令段拷贝多次。

示例2:不定重复伪指令irp

PS:如上图所示,irp指令不指定重复次数,而是根据自变量表中变量的个数确定重复的次数。同样多次拷贝指令段,每次拷贝使用不同的变量代入哑元。

示例3:不定重复伪指令irpc

PS:如上图所示,irpc指令同irp类似,但其自变量表替换为一个字符串,根据字符串中字符的个数确定重复的次数,每次拷贝指令段使用不同的字符代入哑元

伪指令汇总

定义:除以上提到的指令之外,仍有大量伪指令是不那么常用,但于某些状况下十分便利的。

示例1:处理器选择伪指令汇总

PS:以上指令用于选择此后的汇编指令于何种操作系统中执行

示例2:段定义伪指令汇总

PS1:段定义可配合如上图2的各类参数对各段实现特化,也可配合如上图3的存储模式对段使用的存储空间进行精细定义。

PS2:如上图4所示,可使用简化的段定义指令来定义程序段,此种方式在编写小程序时常用,十分便利

PS3:如上图5所示为使用简化的段定义指令示例,其中左端为原程序,右端为简化后程序。注意使用.stack定义栈段之后于代码段中不再需要对ss与sp进行赋值

示例3:程序开始与结束的伪指令汇总

PS:如上图2,左为使用了简化的程序开始、结束标记。右为原程序开始与结束标记。同段定义标记简化,此种方式适合小程序。

示例4:数据定义及存储器分配伪指令汇总

PS:如上图1,此类伪指令已于文章上部进行过解析。此处只分析上图2的label伪指令,该指令用于为一段存储空间赋予新的类型。如以上代码使用dw字型数据定义了一段空间,那么在使用word_array调用时默认其为字型数据。但在前段加上byte_array label byte便等于令其可被视为字节型数据。由此当使用byte_array调用时默认其为字节型数据。

示例5:表达式赋值伪指令汇总

PS:如上图,可用equ或=实现类似定义常量的操作。

示例6:地址计数器与对准伪指令汇总

PS:如上图,以上指令用于对相对地址进行更改,如在使用了org 10后定义的1234h的起始地址将为ds:0010。

示例7:基数控制伪指令汇总

PS:如上图,默认的基数为十进制,当在程序中定义数据并不加任何进制标识时,默认该数据为十进制数据。通过修改基数,可以改变默认进制。

示例8:条件汇编伪指令汇总

PS:如上图所示为条件汇编中使用的指令,其应用见汇编学习笔记——设计与执行的条件汇编部分;关于其中提到的第一遍、第二遍扫视,见汇编学习笔记——设计与执行的程序编译部分。

汇编学习笔记——伪指令相关推荐

  1. 汇编学习笔记——汇编指令

    目录 汇编指令 nop指令 mov.add.sub指令 adc.sbb指令 and.or指令 移位指令 逻辑左/右移指令 循环左/右移指令 算术左/右移指令 带进位循环左/右移指令 inc指令 pus ...

  2. 汇编学习笔记:对抗反汇编实验2019092801

    汇编学习笔记:对抗反汇编实验2019092801 实验描述 实验环境 实验过程 实验结论 实验描述 使用相连的jz和jnz指令跳转到紧接着jnz指令的call指令的第二个字节.call指令实际上无效. ...

  3. GNU C内嵌汇编学习笔记

    前文所述,只是针对汇编格式的整理,本文将使用coreboot项目代码对其进行实例化.以方便.清晰了解到如何在C语言里使用内嵌汇编的方法.同样地,网络上也有众多文章涉及到这方面,所以本文更多是归纳总结. ...

  4. 寄存器---汇编学习笔记

    第二章 寄存器 2.0 寄存器的绪论 一个典型的CPU由运算器.控制器.寄存器(CPU工作原理)等器件构成.内部总线实现 CPU 内部各个器件之间的联系,外部总线实现CPU和主板其他器件的联系. 在C ...

  5. 汇编学习笔记(4)-伪指令(MASM)

    前言 编写汇编代码的时候会使用到两种语句,一种就是前面介绍的汇编指令又CPU提供功能支持,另一种呢叫做伪指令,伪指令是由汇编的编译器提供支持.所以伪指令的运行结果都必须实在编译的时候就能确定的,下面介 ...

  6. 第一个程序---汇编学习笔记

    第四章 第一个程序 4.1 一个源程序从写出到执行的过程 一个汇编语言程序从写到最终执行的简要过程. 编写汇编源程序 对源程序进行编译连接 执行可执行文件中的程序 如图所示: 4.2 源程序 程序代码 ...

  7. 使用BIOS进行键盘输入和磁盘读写---汇编学习笔记

    汇编笔记 使用BIOS进行键盘输入和磁盘读写 17.1 int 9中断例程对键盘输入的处理 17.2 使用int 16h中断例程读取键盘缓冲区 17.3 字符串的输入 17.4 应用int 13h中断 ...

  8. 数据处理的两个基本问题---汇编学习笔记

    数据处理的两个基本问题 计算机是进行数据处理.运算的机器,那么有两个基本的问题就包含在其中: 要处理的数据在什么地方? 要处理的数据有多长? 我们定义两个描述性符号:reg和sreg. reg的集合包 ...

  9. 包含多个段的程序---汇编学习笔记

    包含多个段的程序 要使用一段安全的空间,第五章中我们说0:200~0:2ff是相对安全的.可这段代码容量只有256个字节. 合法地通过操作系统取得的空间都是安全的. 程序取得所需空间的方法有两种,一是 ...

最新文章

  1. Javascript的prototype
  2. MongoDB之bson的介绍
  3. 使用Windows命令行启动服务
  4. 深入理解javascript原型和闭包(18)——补充:上下文环境和作用域的关系
  5. 知乎:学计算机的女生都怎么样了?
  6. 云应用性能管理哪家强?性能魔方mmTrix自动测评、检测与加速
  7. 多数据源与动态数据源的权衡
  8. PHP住院收费系统管理,住院收费管理系统
  9. 无线传感器网络:LEACH路由协议优化python仿真代码
  10. echarts:基于上一篇我来给大家讲讲 如果你设置了自动播放但是鼠标放上去不生效 停留时间很短 应该怎么做呢???
  11. Centos 系统折腾
  12. shader基础学习摘要(二) 兰伯特光照模型
  13. Life feelings--6--有一天感到没有动力了怎么办?--怎样找到持久的热情?
  14. 《过故人庄》古诗鉴赏
  15. 手机、彩电巨头跨界互博
  16. Linux 文件服务器配置
  17. 【已解决】(魅族)手机usb调试模式连接不上电脑
  18. jzoj5224 [GDOI2018模拟7.12]C 杜教筛+自然数幂和
  19. django讲解 模型一
  20. 仓禀实而知礼节,衣食足而知荣辱

热门文章

  1. mysql查询问题sql语句_询问一个SQL查询语句的有关问题,MYSQL的,来看看吧
  2. Class-Aware Robust Adversarial Training for Object Detection论文阅读笔记
  3. window.localStorage.setItem的理解与使用
  4. Ubuntu虚拟机联网问题的解决(配置静态IP)
  5. 九月十月百度人搜,阿里巴巴,腾讯华为小米搜狗笔试面试六十题
  6. matlab 跳转到函数,matlab中fmincon函数如何调用??
  7. 【非参数统计02】单一样本的位置推断问题:符号检验、分位数推断、Cox-Staut趋势存在性检验、随机游程检验、Wilcoxon符号秩检验、位置参数区间估计、正态记分、分布一致性检验、稳健性评价
  8. 星计划---水晶球(1)(函数)
  9. 怎样扩展摩托罗拉的手机内存
  10. 如何用HTML制作课程表