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 标号
标号也就是一种标识符,是指令和数据的位置标记。标号位于指令前端,表示指令的地址,同时也可以位于变量的前端,表示变量的地址。标号有两种类型:数据标号和代码标号。
数据标号标识变量的位置,提供了一种方便的手段在代码中引用该变量。例如:
汇编器为每一个标号分配一个数学位置。可以在一个标号后面定义多个数据项。
例子:
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指令,在程序中不做任何作用,但是占有一个字节,常用来将代码对其,把单字节变成偶数字节
来源:https://www.cnblogs.com/Sna1lGo/p/13375353.html |