前言

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

  注意接下来介绍的伪指令都是基于MASM汇编编译器,比较常用的还有NASM 它的语法以后有机会介绍

数值表达式

  数值表达式不是汇编指令,表达式的值是在汇编代码的汇编过程中就由汇编编译器计算出结果而写到二进制程序中了,并不是在程序运行的过程中才计算的

  (1) 常数表达式

    常数就是直接的数字,直接写数字默认表示10进制数,也可以用符号指定为其他进制

    D = 十进制   ; MOV AL, 1234D

    B = 二进制   ; MOV AL,  0101B

    H = 十六进制  ; MOV AL,  0FFFFH , 注意常数必须是数字开头不能是字母开头,如果16进制数第一个数字是字母的话就要补一个0在前面

    Q = 八进制   ; MOV AL, 123Q

    因为在程序中字母也是数字,所以其实也可以直接将字母或者字符串当成数字,比如

    MOV AL, 'a'

    MOV AX,"ab"  ; 双引号和单引号都是可以使用的

  (2) 算数运算符

    就是简单的 正(+) 负(-) 加(+) 减(-) 乘(*) 除(/) 模(mod)

    mov ax, 100+200

    mov ax, 100/2

  (3) 关系运算符

    等于(EQ) 不等(NE) 大于(GT) 小于(LT) 大于等于(GE) 小于等于(LE)

    如果等式成立则实际的值为0FFFF就是补码表示的-1, 如果关系不成立那么结果就是0

    mov ax, 123 gt 234

    mov ax, 1234+5 lt 1235

  (4) 逻辑运算 

    与(and) 或(or) 非(not) 异或(xor) 左位移(shl) 右位移(shr)

    mov ax, 1 shl 3

    mov al, 3 and 47

  (5) 其他操作符

    HIGH LOW WIDTH MASK 

    HIGH 表示取数据的高八位

    LOW 表示取数据的低八位

地址表达式

  地址表达式所表示的是存储器操作数的地址。前面介绍的各种寻址方式实际上也是地址表达式。

  一般格式是

  mov ax, varw+4

  注意 varw 变量或者标号的地址,这个是在编译的时候就知道的,所以varw+4 计算出来的就是varw 地址偏移4的地址,所以AX的值不是 varw+4的值,而是varw+4 内存地址处的值,所以AX的值是不确定的。

  当然还有其他的写法

  [varw+bx]

  varw[bx]

  varw[bx+di]

  varw[bx][di]

变量和标号

  (1) 数据定义语句

    [变量名]  变量类型 表达式[, 表达式]

    其中变量类型有

    DB  字节

    DW  字

    DD   双字

    

    所以数据定义就可以是这样的

    a db 1,2,3,4,5

    db 7,8,9,10

    b dw 123,123,123

    c dd 123,?,?,?

    汇编中的数据定义意义其实就是C中的数组指针。这些数据都是顺序存放在内存中的,所以虽然第二行的数据没有定义名字,但是因为他紧跟在a 数组之后 b数组之前,所以使用a+5,或者 b-1 也是可以访问的,只是需要注意的是数据类型和 大端小端的问题。

    后面跟实际数据的就表示定义的时候就直接初始化了数据,如果只是想留着位置,并不需要初始化的话也可以使用? 表示,?的意思就是只留位置不初始化内容

  

    前面也说过,字符其实也可以表示为数字,所以也之后直接定义字符数组,下面的两种方式都是可行的

    str  db “hello”

    str db "h","e","l","l","0"

  

  (2) 循环定义 DUP

    数字表达式 DUP(数据[, 数据,数据...])

    有时候定义数组只是想预留一些空间,可能需要预留100个字节那么使用

    buff db ?,?,?,?.......?

    这种方式要打100个? 这样显然很没效率所以有个伪指令可以帮忙

    buff db 100 dup(?);   定义100个DB 数据不用初始化

    也可以这样

    buff  db 5 dup("ab") = buff db 'a','b','a','b','a','b','a','b','a','b'

    dup 也是可以嵌套的比如

    buff db 2 dup(1,2,5 dup(?)) =  buff db 1,2,?,?,?,?,?,1,2,?,?,?,?,?

  (3) this   

     this 类型

     类型可以是byte word dword this返回下一个将分配的地址的

    my_byte equ this byte  ; equ是等效定义符号,下面或解释

    my_word dw 8 dup(?)

    这样就是定义了一个 byte的地址指针指向了一个 word数组等效的C语言就是

    short[8]  my_word[];

    byte* my_byte = (byte*)my_word;

  (4) 等价语句  EQU

    符号名 EQU 表达式

    说白了 EQU 就类似C的 #define 语句

    用法可以是这样的

    COUNT EQU 100      ; #define COUNT 100

    BUFF_EN EQU 4*COUNT  ; #define BUFF_EN  4*COUNT

    HELLO EQU "how are you"   ; #define HELLO "how are you"

    MOVE EQU MOV        ;#define MOVE MOV

   

    VARW EQU THIS WORD  ; 这个就和#dfine不一样了意义上面说过

    VARB DB 2 DUP(?)

  

  (5) 等于语句 =

     符号名 = 数值表达式

    其实就是专用的 EQU,功能和EQU是一样的,只不过试用范围比EQU小,只能用在数值表达式上

    x = 10 ;  x equ 10

    y =20 +50*60 ; y equ 20+50*60

  

  (6) 定义符号名语句

    符号名 LABEL 类型

    类型可以是 BYTE WORD DWORD NEAR FAR

    他的作用其实应该是包含上面 this 指令中的用法即

      my_byte equ this byte

      my_word dw 8 dup(?)

      换成LABEL的写法就是    

      my_byte label byte 

      my_word dw 8 dup(?)

   同时LABLE 还比this强大就是还能作用在标号上

   quit label far

   exit: mov ah,4ch

   这样的用法就 mov ah,4ch这条指令同时拥有 exit的短调指令和quit的长跳指令了。

  (7) 变量和标号的属性

    变量和标号的属性无非就是对应的类型 地址 大小等,对应的操作符

    LENGTH SIZE OFFSET SEG TYPE PTR

    seg 返回变量或标号的段地址    假设 VAR 的地址是 100+2   那么mov al, seg var ; al=100

    offset 返回变量或标号的偏移地址  假设 VAR 的地址是 100+2   那么mov al, offset var ; al=2

    type 返回变量或标号的类型   字节=1 字=2 双字=3 近=-1 远=-2,变量类型就是实际占用的字节数

    length 返回的是DUP定义的长度  DUP将在下面讲到, 注意这里返回的是个数,如果数组没用DUP那么总是返回1 如果嵌套了就返回最外层的

    size  返回DUP定义的实际占用字节数

    ptr  强制类型转化 就是C语言中的(int)A;的作用 用法就是     类型 ptr  变量/数据地址  类型可以是 byte word dword near far

        例如:

        mov word ptr [si],1

        jmp far ptr ok

优先级

   1. 各种括号,LENGTH SIZE WIDTH MASK

   2. PTR OFFSER SEG TYPE THIS 冒号

   3. * / shl shr

   4. HIGH LOW

   5. + -

   6. eq ne lt le gt ge

   7. not

   8. and

   9. or, xor

   10. short

程序组织伪指令

  这些指令是为了方便汇编程序的结构组织的

  (1) 段定义语句

    为了与存储器的分段结构相对应,所以汇编指令也提供了对应的段的组织方式

    段的开始

      段名 SEGMENT [定位类型] [组合类型] [‘类别’]

      。。

    段的结束

      段名 ENDS

    例子

    ;数据段

    DSEG SEGMENT

    MESS DB 'HELLO'

    DSEG ENDS

    ;代码段

    CSEG SEGMENT

      MOV AX, DSEG

        ...

        ...

    CSEG ENDS

  (2) 段使用设定语句

    ASSUME 段寄存器名: 段名 [, 段寄存器名: 段名, 段寄存器名: 段名 ..]

    设定了段之后汇编程序需要知道各自段对应是用来干嘛的,并设置对应的段寄存器。ASSUME就是这个作用

    ASSUME CS: CSEG,DS:DSEG

    ASSUME 是伪指令所以汇编编译器其实是将其转换成了对应的汇编指令,所以ASSUME可以出现在代码段的任何位置。随时进行切换

    这里有个需要注意的是,如下代码

    DSGE1 SEGMENT

        .....

    DSGE ENDS

    DSEG2 SEGMENT

        ......

    DSGE2 ENDS

    CSEG SEGMENT

    ASSUME CS:CSEG DS:DSEG1 ES:DSEG2

    MOV AX,DSEG1      ; 由于此时数据段就是DSEG1 所以指令就是直接翻译的

    MOV AX,DSEG2      ; 由于此时数据段是DSEG1,所以实际语句会被翻译成 MOV AX, ES:DSEG2

  (3) ORG 指令

    ORG 数值表达式

    汇编编译器在汇编的时候使用汇编地址计算器来计算每条指令的偏移地址,而ORG指令就是用于手动修改当前地址的

    比如

    test segment

       org 100h

    begin: mov ax,1234h

    test ends

    mov ax,1234h 是段内的第一条语句偏移应该是0 ,但是由于ORG 100H的缘故,实际的偏移地址就变成了100H

  

  (4) 当前地址 $

    $表示当前指令的第一个字节的地址

    org $+8 表示表示地址计算器从此处开始向后空8个字节出来

    他也可以用在其他指令中,比如

    jmp  $+ 6 ; 转跳到本条指令之后6个字节处,注意计算地址是JMP指令的开始位置不是结束位置,所以这6个自己包含了JMP本身的长度

    ARRAY 1,2,$+4; 这里的% 表示的是ARRAY的地址不是 $ +4的地址

转载于:https://www.cnblogs.com/alwaysking/p/7623781.html

汇编学习笔记(4)-伪指令(MASM)相关推荐

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

    目录 伪指令 段定义 结束标记 段关联标记 数据定义 标号 offset指令 seg指令 地址标号 数据标号 代码分段 程序标识 多文件系统 字符输入 重复定义 注释 重复汇编伪指令 伪指令汇总 伪指 ...

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

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

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

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

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

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

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

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

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

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

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

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

  8. 汇编学习笔记(二):转移指令

    章节目录 转移指令原理 jmp 指令 jcxz 指令 loop 指令 ret 和 retf 指令 call 指令 call+ret 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人 ...

  9. Win32汇编学习笔记之基础篇

    基础篇 第一章 背景知识 1.1 Win32的软硬件平台 1.1.1    80x86系列处理器简史 Win32可以在多种硬件平台上运行,但使用最广泛的硬件平台是基于Intel公司80x86系列处理器 ...

最新文章

  1. ubuntu 安装 Terminator
  2. PHP自动加载__autoload的工作机制
  3. MySQL学习笔记02-数据库概述及MySQL简介 .
  4. 明天mbzuai面试的准备,严阵以待
  5. Matlab repmat函数
  6. java监听器原理_java监听器原理
  7. 常见面试题思想方法整理
  8. WebService工具类调用远程接口服务时java.io.IOException: Server returned HTTP response code: 500 for URL XXX
  9. 为什么李彦宏会候选院士?
  10. Bailian2767 简单密码(POJ NOI0107-10)【密码】
  11. python官网的软件-python软件怎么用
  12. iOS导航控制器和Segues
  13. Python基础知识之面向对象编程
  14. php漫画源码,小涴熊漫画CMS:开源的PHP漫画源码
  15. 【吃豆游戏----HTML+JS+CSS等实现,效果+源代码】
  16. 大学计算机aoa学什么,浙江省高校计算机二级AOA考试excel试题及解析.xls
  17. 日文输入法快捷键整理
  18. Word分栏出现空白怎么解决
  19. 审慎 合宜与慈善三种学派的分类与核心思想
  20. 读 Frank Thilly 之《西方哲学史:修补增订版》

热门文章

  1. mac mysql mysqldump_Mac下Mysql导出sql语句的方法及可能遇到的mysqldump: command not found...
  2. python买菜打折优惠
  3. php mysql 大量读取_PHP使用PDO从mysql读取大量数据处理详解
  4. Scala入门到精通——第四节 Set、Map、Tuple、队列操作实战
  5. Spark配置参数详解
  6. 用户特征工程详细解读
  7. 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(二)
  8. SQL语句错误:Operand should contain 1 column(s)【查询多个字段不用加括号】
  9. POST方式发起下载请求
  10. 超好用!5款开源的移动自动化测试工具