1   基本语言元素:

  本次汇编语言学习,采取的是Microsoft MASA的汇编器语法规则。

1.1 第一个汇编程序

 

1 main PROC      
2     mov eax,5  ;把数字5送入寄存器eax
3     add  eax,6  ;eax寄存器加6
4     
5     INVOKE ExitProcess,0 ;程序结束
6 main ENDP  ;结束标记

  这个程序实现的是将寄存器eax赋值为5并自加6然后退出。

  采用一行一行结束这个代码:第一行的main PROC 是程序的入口,相当于一个C语言的main函数

  第二行是mov eax,5把数字5送入寄存器

  第三行把6加到寄存器eax上。

  第五行 调用windows服务(函数)ExitProcess停止服务。

  第六行 作为主程序结束的标志。

 

1.2 程序分段

  为了使程序更加一目了然,架构清楚,需要添加一些标记或声明来标识程序的代码和数据区分区。

  程序有代码段,数据段,堆栈段等等。

 1 .data     ;定义为数据区    
 2 sum DWORD 0 ;申明变量sum类型为DWORD,初值为0
 3 
 4 .code     ;定义为代码区
 5 main PROC
 6     mov eax,5
 7     add  eax,6
 8     mov sum,eax  ;将eax寄存器的值赋值给sum变量
 9     
10     INVOKE ExitProcess,0    ;程序结束
11 main ENDP

1.3 整数变量

格式:

[{+ | -}] digits [radix]

首先符号表示,如果为正可以省略,中间是数值,radix是基数也就是进制,如果为十进制可以省略

进制需要用缩写来表示

二进制 八进制 十进制 和十六进制的缩写分别是 B Q D H来表示

例子:

26    ;十进制
26D    ;十进制
11b    ;二进制
1Ah    ;十六进制
42q    ;八进制

需要注意的是如果十六进制是用字母开头的需要在前面添加一个0防止汇编器把该数作为标识符

1.4 整形常量表达式

也就是比平时的加减乘除多了一个取模运算

运算优先级

运算符 名称 优先级
()     括号 1
*  / 乘除 2
MOD 取模 3
+ - 加减 4

1.5 实数常量

实数常量又叫浮点数常量,用来表示十进制的实数和编码(十六进制)实数。十进制数包含一个可选符号,然后整数,然后小数点和一个可选小数部分整数和一个可选指数

【sign】integer.[integer][exponent]

sign 取值{+,-}

exponent 取值 E[{+,-}]integer

例子:

 2.

 +3.0

 -44.2E+05

 26.E5

 

1.6 字符常量

  字符常量是指用单引号或者双引号包含的一个字符,汇编器在内存中保存的是字符的ASCII码的数值

例如 'A' 就是保存的对应的ASCII码数值保存为数字65或41h

1.7 字符串常量

  字符串常量(string literal)是用单引号或双引号好汉的一个字符序列(包括了空格符等等),嵌套引号使用也是被允许的。

和字符常量保存一样,字符串常量只是一个一个拆分成字符常量保存在内存中。

  例如:"ABCD"就包含四个字节41h,42h,43h,44h。

 

1.8保留字

  也就是C语言的关键字的意思,这些保留字都是在汇编语言中有特殊含义的,不能随便用。保留字没有大小写的区分,比如MOV和Mov是一样的。

分类:

指令助记符:

  如 MOV,ADD和MUL

寄存器名称:

  如:eax

伪指令:

  也就是告诉汇编器怎么编程序,比如分段.data,.code这种

属性:

  变量的属性,比如BYTE和WORD

运算符

预定义符号

  在之前就定义了的,比如@data在汇编时返回常量的整数值

 

1.9 标识符(identity)

  由程序员自己选定的名称,用来标识变量,常数,函数,子程序代码等等。

  标识符的规则:

    1.包含所有字符

    2.不区分大小写

    3.第一个字符必须以字母,下划线,@ ?或%来处理

    4.标识符不能和保留字冲突

    5.通常避免用@和下划线作为第一个字符

 

1.10 伪指令

  伪指令(directive)是嵌入源代码中的命令,由汇编器识别和执行。汇编器不允许的时候执行伪指令,但是伪指令可以定义变量,宏,和子程序。给内存段分配名称。默认情况下,伪指令不区分大小写。

  由下面例子区分指令和伪指令:

  

test DWORD 26
mov    eax,test

  DWORD伪指令告诉编译器在程序中保留一个双字空间。mov指令在运行时,将test内容复制到eax寄存器中。

  需要注意的是Intel处理器的所有汇编器使用相同指令集,但是有着不同的伪指令。

  伪指令的功能:定义段

    汇编器伪指令的一个重要功能就是定义程序区段,也叫段(segment),程序中的段有不同作用,

      .

.data    ;数据段在这里申明变量

.code    ; .code伪指令标识的程序区段包含了可执行的指令

.stack 100h    ;.stack伪指令的程序区段定义了运行时的堆栈大小

 

1.11 指令

  指令是一种语句,在程序汇编编译时变得可执行,汇编器将指令翻译为机器语言字节,并且运行时由CPU加载执行。

  一条指令由四个部分组成:

    1.标号(可选)

    2.指令助记符(必需)

    3.操作数(一般是必需)

    4.注释(可选

;一般格式
[label:] mnemonic [oprands] [;comment] 

  1.11.1 标号

    标号也就是一种标识符,是指令和数据的位置标记。标号位于指令前端,表示指令的地址,同时也可以位于变量的前端,表示变量的地址。标号有两种类型:数据标号和代码标号。

    数据标号标识变量的位置,提供了一种方便的手段在代码中引用该变量。例如:

 

count DWORD 100

      汇编器为每一个标号分配一个数学位置。可以在一个标号后面定义多个数据项。

例子:
    array DWORD 1024,2048
             DWORD   4096,8192        

    代码标号:

         代码标号用作跳转和循环指令的目标。

         代码标号必须用冒号 : 来结束

;例子,下面的JMP指令创建一个循环,将程序控制传递给标号target表示的位置
target:
  mov  ax,bx
  ...
  jmp  target

         代码标号可以与指令在同一行,也可以自己独立一行

  1.11.2 指令助记符

    指令助记符(instruction mnemonic)是标记一条指令的短单词。

    例子:

    

助记符 说明
MOV 传送(分配)数值
ADD 两个数值相加
SUB 从一个数值减去另一个数值
MUL 两个数值相乘
JMP 跳转到一个新位置
CALL 调用一个子程序

  1.11.3 操作数

    操作数也就是指令输入输出的数值,汇编语言的操作个数是0-3个。可以是寄存器,内存操作数,整数表达式和输出输入端口。

    例子:

    

示例 操作数类型
96 整数常量
2+4 证书表达式
eax  寄存器
count 内存

    操作数个数示例:

    

stc    ;进位标志位置,没有操作数

;一个操作数
inc    eax    ;eax加一

;两个操作数
mov eax,5     ;把5赋值给寄存器eax

;三个操作数

imul    eax,ebx,5    ;ebx和5相乘的结果赋值给eax

 

  1.11.4 注释

    单行注释 采用分号(;)

    多行注释,用COMMENT伪指令和一个自定义符号开始。

COMMENT    I
    THIS is a comment
    this is also a comment
I

  

 

  1.11.5 NOP(空操作)指令

    nop指令,在程序中不做任何作用,但是占有一个字节,常用来将代码对其,把单字节变成偶数字节