汇编基础①

基于《CTF竞赛权威指南 PWN篇》的总结。

CPU架构与指令集

CPU:中央处理单元,也称处理器,作用为从内存中读取指令,然后解码和执行。
CPU架构:CPU的内部设计和结构,也称微架构,用于实现指令集规定的操作或运算。
指令集架构:简称指令集,包含了一系列操作码以及由特定CPU执行的基本命令。

CPU操作模式

x86处理器:保护模式、实地址模式、系统管理模式,还有一个保护模式的子模式,称为8086模式。
保护模式:处理器的原生状态,此时所有指令和特性都可用,分配给程序的独立内存区域称为内存段,处理器将阻止程序使用自身段以外的内存区域。
实地址模式:早期Intel处理器的编程环境,程序可直接访问硬件及其实际内存地址。
系统管理模式:为操作系统提供了如电源管理和安全保护等特性机制。

语法风格

x86汇编语言主要的语法风格有:AT&T和Intel

AT&T语法风格Intel语法风格
寄存器前加%符号寄存器前无符号表示
立即数前加$符号立即数前无符号表示
16进制数使用0x前缀16进制数使用h后缀
源操作数在前,目标操作数在后目标操作数在前,源操作数在后
间接寻址使用()表示间接寻址使用[]表示
操作位数为指令+l、w、b操作位数为指令+dword ptr等
间接寻址格式%sreg:disp(%base,index,scale)间接寻址格式sreg:[basereg +index *scale +disp]

寄存器与数据类型

寄存器

64位模式下,操作数的默认大小仍为32位,且有8个通用寄存器,当给每条汇编指令增加REX(寄存器扩展)的前缀后,操作数变为64位,且增加8个带有标号的通用寄存器(R8~R15)。
64位处理器与32位处理器有相同的标志位状态。64位模式下不能访问通用寄存器的高位字节(如AH、BH、CH、DH)。

整数常量

不同的进制需加后缀区分,此外,以字母开头的16进制数还需加上前缀’0’,如0ABCDh。

浮点数常量

也称实数常量,通常以十进制表示浮点数,而以十六进制编码浮点数,浮点数至少包含一个整数和一个十进制的小数点。

字符串常量

用单引号或双引号括起来的字符序列,包括空格符,可以嵌套。

数据传送与访问

MOV是最基本的数据传送指令,基本格式中,第一个参数为目的操作数,第二个参数为源操作数,如MOV EAX,ECX表示将ECX寄存器的值拷贝到EAX中。MOV支持从寄存器到寄存器、从内存到寄存器、从寄存器到内存、从立即数到内存、从立即数到寄存器的数据传送,但不支持从内存到内存的直接传输,想要完成内存到内存,需要一个寄存器作为中转。
对不同位数寄存器的数据传送eg:

MOV EAX,0				;EAX=00000000h
MOV AL,78h				;EAX=00000078h
MOV AX,1234h			;EAX=00001234h
MOV EAX,12345678h		;EAX=12345678h

x86汇编语言使用变量名+偏移量表示一个直接偏移量操作数,如下表示一个数组:

.data
	testArray BYTE 99h,98h,97h,96h
.code
	MOV al,testArray		;al=99h
	MOV bl,[testArray+1]	;bl=98h
	MOV cl,[testArray+2]	;cl=97h

某些汇编器未实现数组的边界检查,如果偏移量超过了数组的实际定义范围,将出现数组越界错误。

算术运算与逻辑运算

最简单的算术运算指令为INC和DEC,分别用于操作数+1和-1,这两条指令的操作数既可以是寄存器,也可以是内存。

.data
	testWord WORD 1000h
.code
	INC EAX
	DEC testWord

计算机底层数据表示均由补码表示。
ADD指令将长度相同的操作数相加。

.data
	testData DWORD 10000h
	testData2 DWORD 20000h
.code
	MOV EAX,testData			;EAX=10000h
	ADD EAX,testData2			;EAX=30000h

SUB指令为减法操作。

.data
	testData DWORD 20000h
	testData2 DWORD 10000h
.code
	MOV EAX,testData			;EAX=20000h
	SUB EAX,testData2			;EAX=10000h

汇编语言中存在标志位寄存器,使用ADD和SUB等指令都可能造成整数溢出、符号位等标志发生变化。
NEG指令是把操作数转换为二进制补码,并将操作数的符号位取反。

跳转指令与循环指令

条件跳转:满足特定条件时跳转
无条件跳转:无论标志位寄存器为何值,都跳转。
JMP指令:无条件跳转

		JMP label1
		MOV EBX,0
	label1:
		MOV EAX,0

JMP指令可创建循环,即循环结束时用JMP跳回开头。
LOOP指令也可以创建一个循环代码块,ECX寄存器为循环计数器,每循环一次,ECX-1

MOV AX,0
MOV ECX,3
L1:
INC AX
LOOP L1
XOR EAX,EBX

LOOP指令分为两步,一是ECX-1,二是将ECX与0比较,若不为0,则跳转;若为0,则不跳转。若将ECX初始值设为0,那么ECX-1实际为FFFFFFFFh,是一个非常大的循环。

栈与函数调用

栈的主要用途:存储局部变量、执行CALL指令调用函数时,保存函数地址、传递函数参数。
栈的常用指令为PUSH和POP,即入栈和出栈。
通过栈实现EAX和EBX的交换eg:

MOV EAX,1234h
MOV EBX,5678h
PUSH EAX
PUSH EBX
POP EAX
POP EBX

在这里插入图片描述
CALL指令调用某个子函数时,下一条指令的地址作为返回地址被保存到栈中,等价于PUSH返回地址与JMP函数地址的指令序列。被调用函数结束时,程序执行RET指令跳转到这个返回地址,将控制权交还给调用函数,等价于POP返回地址与JMP返回地址的指令序列。
调用子函数这一行为使用PROC与ENDP伪指令来定义,且需要分配一个有效标识符,所有x86程序中都包含标识符为main的函数,main函数不需要使用RET指令,其他的都需要使用。

1 ... 				.code
2 ... 				main PROC
3 0x00008000 		MOV EBX,EAX
4 ... 				...
5 0x00008020 		CALL testFunc
6 0x00008025 		MOV EAX,EBX
7 ... 				...
8 ... 				main ENDP
9 ... 				...
10 0x00008A00 		testFunc PROC
11 ... 				MOV EAX,EDX
12 ... 				...
13 ... 				RET
14 ... 				testFunc ENDP

第五行的CALL执行时,将下一条指令的地址0x00008025压入栈中,被调用函数testFunc的地址0x00008A00则被加载至EIP寄存器中。
当执行13行的RET时,ESP指向的数据将被弹出至EIP寄存器,ESP的数值增加,将只向栈中的上一个值。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值