汇编语言基础教程

本文详细介绍了X86架构中的各种寄存器(如通用寄存器、段寄存器、调试寄存器、控制寄存器和标志寄存器)及其在程序执行中的作用,包括栈的管理、内存分段、浮点运算和控制流。还讨论了函数调用的规则和机器码操作细节。
摘要由CSDN通过智能技术生成

物质

通用寄存器

栈是预先分配好的,连续的内存空间,以防止频繁分配,导致程序卡顿

e : extended 扩展 enhance增强 extra

AH&AL=AX AX为EAX的低16位, AH(high)为AX的高8位,AL(low)为AX的低8位

  • ax a : accumulator 累加 加法减法的结果,用以传递返回值
  • bx b : base 基址
  • cx c : count 计数 for循环 ,用来传递ecx的this指针,保存到esi中
  • dx d : data 数据 32位相乘结果为64时,edx放高位,eax放低位

索引寄存器

i : index

si/di source/destination 源/目标索引寄存器,内存复制时常用

栈指针

p : pointer

  • bp b : base 基指针,栈底,this指针
  • sp s : stack 栈指针,栈顶小,栈底大,
  • ip i : instruction 当前执行的命令的指针

段寄存器

段寄存器用于实现内存分段机制,将内存划分为不同的段,每个段都有自己的基地址和长度。实现内存分段、内存保护、段间跳转和任务切换等重要功能

选择子(Selector)是 x86 架构中用于标识一个段的标识符,它由两个部分组成:索引(Index)和表(Table)。

  • CS:代码段寄存器,用于存储当前代码段的选择子。在执行指令时,CS:IP(指令指针寄存器)指向下一条要执行的指令。
  • DS:数据段寄存器,用于存储当前数据段的选择子。在访问全局变量和静态数据时,使用 DS 寄存器来计算实际的物理地址。
  • ES、FS、GS:附加数据段寄存器,用于存储其他数据段的选择子。这些寄存器可以用于访问额外的数据段,例如访问一个大型数据结构或其他特定的数据段。
  • SS(stack):栈段寄存器,用于存储当前栈段的选择子。在函数调用和返回过程中,使用 SS 寄存器来访问栈中的局部变量、函数参数和返回地址。

调试寄存器

Debug Register

  1. DR0-DR3:这些寄存器用于设置硬件断点的地址。每个寄存器可以存储一个断点地址。
  2. DR4-DR6在做调试器需要硬件断点(CPU的IO)时使用
  3. DR7:也称为调试控制寄存器,用于配置调试寄存器的工作模式和断点设置。它包含多个位字段,每个位用于配置一个调试寄存器的断点类型和长度。DR7其中的8bit来控制DR0-DR3,其中L0-L3置1表示该寄存器\生效,G0-G3置0表示只对当前任务有效

控制寄存器

Control Register

  1. CR0:CR0 是一个 32 位的控制寄存器,用于控制处理器的基本操作模式和系统特性。它包含多个位字段,用于启用或禁用分页、保护模式、浮点处理、缓存等功能。
  2. CR2:CR2 是一个 32 位的控制寄存器,用于存储最近一次发生页面错误时的线性地址。当发生页面错误时,处理器会将引起错误的线性地址存储在 CR2 中,以便操作系统能够处理该错误。
  3. CR3:CR3 是一个 32 位或 64 位的控制寄存器,用于存储页目录表的基地址。页目录表是用于管理虚拟内存的重要数据结构,CR3 寄存器指向当前正在使用的页目录表。
  4. CR4:CR4 是一个 32 位的控制寄存器,用于控制处理器的扩展功能和系统特性。它包含多个位字段,用于启用或禁用分页扩展、物理地址扩展、虚拟 8086 模式、机器检查等功能。
  5. CR8:CR8 是一个 32 位或 64 位的控制寄存器,用于控制中断优先级。它在多处理器系统中用于设置当前处理器的本地中断控制器的中断优先级。

标志寄存器

FL Flags Register

PSW.png

F : flag 一个寄存器的部分位作为标志

  • 条件

OF overflow

SF sign 符号

ZF zero 零标志

CF carry 最高有效位进位或借位

AF auxiliary 辅助进位

PF parity 最低有效字节1的个数的奇偶性 偶数为1

  • 控制

DF direction 方向

IF interrupt 中断

TF trap 陷阱 单步调试

一般规律

函数call

先push ebp, 再将esp赋值给ebp, 然后esp-n来让数据入栈

通过函数头部 sub esp,8可以判断局部变量个数(2个int,4个char…)

正常情况,加减总是对称出现的

分配局部变量是 SUB ESP 10 分配四个局部变量

注 : 栈外数据并未被清除,只是无法访问,等待被新的数据覆盖

**注意 : ebp是最大值,所以入栈为减,出栈为加 **

dword ptr[x] 双字指针,读取出地址x内的数据

运动

nop : no operation

运算

算术运算

sub esp,8 将esp-8后放入esp中

整数
  • 四则运算

add sub mul div + - * /

  • 自增自减

++ inc(increase) – dec(decrease)

  • 左右移

shr shl shift right/left 不保留符号位

sar sal Arithmetic 保留符号位

乘法被优化成位移

lea edx,[eax+eax*8]
;即eax*9 = eax+eax*8

除法可能被优化成乘法,类似补位数减法

mov eax 0xAAAAAAAB
mul x
shr edx,1
mov res,edx
;将除数分解成c = 2^n/m  这里3 = 2^33/0xAAAAAAAB
  • 赋值

mov与lea的区别

mov esi,[edx*4+004B51D0] 
lea eax,[edx*4+004B51D0]
;esi存的是该地址的值,eax存的是这个地址
浮点数

储存到ST0-ST7(stack top),这几个寄存器是在栈的顶部

wait 在早期x86指令中,浮点操作慢,需要等待然后执行下一条指令

  • 数学运算

FADD/FSUB/FMUL/FDIV/FSQRT

  • store and load

STF/LDF FSTCW/FLDCW

浮点数运算相关寄存器

	1. FST(Floating-Point Status):FST是一种浮点数运算的状态标志,用于指示浮点数运算中是否发生了溢出(overflow)或下溢(underflow)。FST标志位通常由浮点处理器设置和更新。
	2. FCW(Floating-Point Control Word):FCW是一种浮点数运算的控制标志,用于控制浮点数运算的行为,例如舍入模式、精度控制等。FCW通常存储在浮点控制字寄存器中,可以通过相应的指令进行读取和修改。
	3. ERR(Error):ERR是指浮点数运算中的错误,例如除以零、无效操作等。当发生这些错误时,浮点处理器会设置相应的错误标志位。
	4. 掩码(Mask):掩码是一种用于控制浮点异常的标志位。通过设置掩码标志位,可以选择是否启用或禁用特定的浮点异常处理。掩码标志位通常存储在浮点控制字中。

可用下面代码来进行检测

#include <iostream>
#include <fenv.h>

int main() {
    // 启用浮点数异常处理
    feenableexcept(FE_INVALID | FE_OVERFLOW | FE_DIVBYZERO);

    float x = 1.0, y = 0.0;
    float z = x / y;  // 浮点数除以0,会出现除以零错误

    std::cout << "z = " << z << std::endl;

    return 0;
}
  • to 与整数转换

F2I/I2F F I ST P 转成整数后存储并弹栈

逻辑运算

and or xor not 一般存在eax中

字符串指令

即针对字符串的操作

s string

rep repeat -有条件重复

stos store string

lods load

scas scan

cmps compare

movs move

跳转

无条件

jmp

所有的jmp都是相对地址

所以$ rel = destaddr - nextaddr $

  1. 短跳转(Short Jump):

    • 操作码:EB xx
    • 跳转范围:-128到+127字节
  2. 长跳转(Near Jump):

    • 操作码:E9 xxxxxxxx

    • 跳转范围:-2,147,483,648到+2,147,483,647字节

call

函数调用跳转,不同的调用约定会将下一条指令放入栈中

有条件

所有的比较都是运算结果跟0比,如je,比较结果等于0时跳转,有下面两种比较

两种运算

test eax,eax  	;按位与(or),改变ZF,SF
cmp eax,ebx 	;减法(sub),改变ZF,SF,OF

标志位

ZF(零标志位)  :	 如果两个操作数相等,则设置为1,否则为0。
SF(符号标志位):	如果结果为负数,则设置为1,否则为0。
OF(溢出标志位):	如果有符号数的溢出发生,则设置为1,否则为0。
CF(进位标志位):	如果无符号数的进位发生,则设置为1,否则为0。

跳转

je	;等于跳转(Jump if Equal),当ZF为1时跳转。
jne	;不等于跳转(Jump if Not Equal),当ZF为0时跳转。
jg	;大于跳转(Jump if Greater),当ZF为0且SF等于OF时跳转。
jl	;小于跳转(Jump if Less),当ZF为0且SF不等于OF时跳转。

传输

数据

push入栈 并减小esp的值

pop出栈 并增加esp的值

地址

lea load effective address 加载该地址到某寄存器中

调用函数时

调用约定

主要是两个

thiscall

call之前会将this指针存到ecx中,在函数执行途中可能会转存到esi中

stdcall

WINAPI常用,由被调用者恢复栈平衡,表现为call中add esp,8

**cdecl **

C declaration,调用者恢复,表现为call之后add esp,8

参数

由左至右入栈,因栈为后进先出,所以第一个参数要最后入栈

返回值

如果有返回值则放进eax后ret

一般表现为call后test eax,eax

ret 8指令并不表示返回值为8,而是表示从栈中弹出8个字节的数据

栈平衡

call //栈里放入原本下一句的地址

push ebp

mov ebp,esp

sub esp,8//可以据此判断局部变量个数

xxx

add esp,8

mov esp,ebp

pop ebp

ret

机器码

reg8/mem8,reg8(16) reg8,reg8/mem8(16) AL/AX,immed8

  1. 前0x4F个为 两个操作数的逻辑运算

每个算术操作和按位逻辑操作的操作数有以上六种组合

每8个一种运算,前6个是运算,后面两个是段寄存器的出栈入栈

00-0F ADD OR

10-1F ADC SBB 进位加法(carry),借位减法(borrow)

20-2F AND SUB

30-3F XOR CMP

40-4F INC DEC

00-07如下,其他类推

00 ADD reg8/mem8,reg8
01 ADD reg16/mem16,reg16
02 ADD reg8,reg8/mem8
03 ADD reg16,reg16/mem16
04 ADD AL,immed8
05 ADD AX,immed16
06 PUSH es 
07 POP es
  1. 对下面八个寄存器的操作

ax cx dx bx 加法/计数/数据/基址 sp/bp 栈/基址指针 si/di 源/目的索引

50-5F PUSH POP

60-6F PUSH/POP A(all) 这是前两个,后面还有,感觉不常用

  1. 跳转

看标志位,操作数为imm,以T/F两两一组

70-7F

JO/JNO(overflow) JB/JNB(below) JZ/JNZ(zero) JBE/JA (below equal/above)

JS/JNS(sign) JP/JNP(parity) JL/JNL(less) JLE/JG(less qual/greater)

后面的算了,没啥规律

对照

英文全称参照

机器码对照

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值