第二章:x86处理器架构
32位x86处理器的操作模式
- 保护模式:是处理器的原生态模式,所有的指令和特性都是可用的,每个程序被分配的独立内存区域叫段,处理器会阻止程序访问除了自己段范围之外的内存,也就是其运用了虚拟内存的技术
- 实地址模式:是早期的Intel处理器的编程环境,可以切换到其他模式,当程序想直接访问系统内存和硬件设备时,这个模式很有用
- 虚拟8086:运行在保护模式下的实地址模式
- 系统管理模式:向操作系统提供实现诸如电源管理和系统安全等功能的机制,通常由计算机制造商实现
- 在32位机下,保护模式的最大寻址4GB,后来通过扩展物理寻址达到64GB,而实地址只有1M,在保护模式下运行虚拟8086,每个程序1M内存空间
- 保护模式下,EA:起始地址 PA:有效地址
x86处理器中的寄存器
-
通用寄存器:主要用于算术运算和数据传输
特殊用法:1. 乘除指令默认使用EAX,它常常被称为扩展累加器 2. ECX用作循环计数器 3. ESP用于寻址堆栈,扩展堆栈指针寄存器 4. ESI、EDI用于高速存储器传输指令 5. EBP引用堆栈中的函数参数和局部变量
-
段寄存器:实地址模式,存放的是预先分配的内存区域的基址;在保护模式下,存放的是段描述符表指针等
-
指令指针(EIP):包含下一条将要执行指令的地址
-
EFLAGS寄存器:用于控制CPU的操作或是反应一些CPU操作的结果
状态标志位
-
F是flag的意思
-
进位标志位(CF):无符号算术运算结果太大时,设置该位
-
溢出标志位(OF):有符号算术运算结果太大或太小,设置该位
-
符号标志位(SF):算术或逻辑操作产生负结果时,设置该位
-
零标志位(ZF):算术或逻辑操作产生的结果为0时,设置该位
-
奇偶校验标志位(PF):结果的最低有效字节包含偶数个1时,设置该位
第三章:汇编语言的基础
汇编语言程序的基本模板
因此程序员可以将自己的汇编程序看作是被操作系统调用的子程序或过程,所以它才能直接的调用硬件
.386 ;表明这是一个32位的程序
.model flat,stdcall ;选择内存模式为flat,并确定了子程序的调用规范(称为stdcall)
.stack 4096 ;运行时堆栈保留4096字节的存储空间,每个程序都必须有
ExitProcess PROTO,dwExitCode:DWORD ;ExitProcess函数的原型,是标准的windows服务
;函数名 关键字 输入参数名称
;可以看作给Windows操作系统的返回值,如果为零,则标识程序执行成功;其他的任何整数值都代表一个错误代码
;因此程序员可以将自己的汇编程序看作是被操作系统调用的子程序或过程,所以它才能直接的调用硬件
.data
;在这里声明变量,例如:变量声明:变量名 数据类型 初始化值
.code;下一行声明程序的入口,一般是一个名为main的过程,是指要执行第一条指令的入口
main PROC
;编写自己的代码
main ENDP;ENDP伪指令标记一个过程的结束
END main;END标记一个程序的结束,并要引用程序入口
汇编语言中的常量
-
整数常量:关注最后一个字母代表什么意思 h:16进制 ;d:十进制;b:二进制;q/o:八进制 ;什么也不写当然是十进制
-
整型常量表达式:例如 4+5*2
-
实数常量:也称为浮点数常量
-
字符和字符串常量:是指用单引号或双引号包含的字符或字符串(含空格符),嵌套引号是被允许的,它们在内存中存放的形式为ASCⅡ编码序列
保留字
有特殊意义并且只能在其正确的上下文使用。
默认情况下,是没有大小写之分的
- 指令助记符,如MOV、ADD
- 寄存器名称
- 伪指令:不区分大小写,可以定义存储单元类型的伪指令BYTE、WORD、DWORD、宏、子程序;为内存段分配名称,其重要的一个功能是可以定义段:如.data .code; 定义过程的伪指令PROC、ENDP ;程序结束伪指令END 详情见[我的博客]((4条消息) 指令和伪指令的区别及作用_m0_49135369的博客-CSDN博客)
- 属性:提供变量和操作数的大小和使用信息,例如BYTE和WORD
- 运算符
- 预定义符号
标识符
- 是由程序员选择的名称,用于标识变量、常数、子程序和代码标签
- 一些规则:不能和保留字相同、不区大小写、第一个字母必须为字母、下划线(不推荐)、@、?、$
指令:是一种语句,在编译后变得可执行,
-
由4个部分组成,标号(可选)、指令助记符、操作数、注释(可选)
-
标号也是一种标识符
-
指令助记符,如 mov、add、sub、mul、jmp、call,是标记一条指令的短单词,给出了指令执行操作类型的线索
-
操作数:寄存器操作数、内存操作数、整数表达式、输入输出端口
-
注释:用分号(;)开始 如果想注释段落可用COMMENT
用 COMMENT !
XXXXXX
!
汇编、链接和运行程序
汇编器生成的机器语言的文件,称为目标文件,这个文件还不能执行,它还需要被传递给一个被称为链接器的程序,从而生成可执行文件,这个文件就准备好在操作系统命令提示符下执行
- 列表文件:包含了源文件的副本、行号、每条指令的数字地址、每条指令的机器代码字节(十六进制)以及符号表
-
B8、83、6A、E8代表操作代码,表示特定的指令 invoke伪指令生成了PUSH、CALL语句
机器指令是以十六进制表示,一个数字代表四位—>改变地址位
定义数据
表3-2中的类型都是伪指令哦!,3-3是传统数据伪指令
数据定义的一般形式
变量名 数据类型 数据初始值
-
数据定义中至少要有一个初始值,即使该值是0,如果不希望对其进行初始化(随机分配数值)可以用**?**作为作为初始值
-
对于字符串定义,要以一个空字节作为结束标记,称为以空字节结束的字符串 如 greeting BYTE “Good afternoon”,0
空格叫空格符
定义数组:
变量名(标识符) 数据类型 初始化的值(多个)
DUP操作符
示例:变量名(标识符) BYTE 20 DUP(0) ;分配20个字节,值都为0
符号常量
等号伪指令
把一个符号名称与一个整数表达式连接起来
例题:COUNT=500
当程序进行汇编时,在汇编器处于预处理阶段,所有的COUNT都会被替换成500
mov eax, COUNT 当汇编时 mov eax ,500
当前地址计数器:$
通常用作求数组的个数
arrayD WORD 1000h,3000h,5000h
ListSize=($-arrayD)/ TYPE arrayD
.data
arrayD WORD 1000h,3000h,5000h
sef DWORD $
mov eax,sef ;疑惑 为什么 sef DWORD $ 这时的sef的值是数组的首地址而不是末地址的下一位
eax ;eax存的是arrayD的首地址?
8208384
&sef
0x007d4006 {$Test.exe!unsigned long sef} {8208384}
&arrayD
0x007d4000 {$Test.exe!unsigned short arrayD} {4096}
.data
arrayD WORD 1000h,3000h,5000h
ListSize=$
mov eax,ListSize
eax;存的是arrayD的最后地址位
2113542
&arrayD
0x00204000
另一个作用是字符串终止,例如’i like zyx$’,在上述字符串中对应于计算机语言中的\0,字符串的终止。