type
status
date
slug
summary
tags
category
icon
password
x86汇编语言
什么是汇编语言
汇编语言是一种低级别的计算机编程语言,它直接使用计算机的机器指令集来编写程序。
汇编语言是汇编指令的集合,而汇编语言可以认作是二进制指令的文本形式。
汇编语言的编程过程主要围绕着如何有效地使用寄存器和内存进行数据操作和控制,以及如何利用指令集来实现所需的计算任务
CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。基本上,CPU 缓存可以看作是读写速度较快的内存。
但是,CPU 缓存还是不够快,另外数据在缓存里面的地址是不固定的,CPU 每次读写都要寻址也会拖慢速度。因此,除了缓存之外,CPU 还自带了寄存器(register),用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。
一、x86架构通用寄存器
8个通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
EAX: 累加器,用于存放函数的返回值。
EBX: 基地址寄存器,主要用于内存寻址时存放基地址。
ECX: 计数寄存器,主要用于循环和字符串操作的计数。
EDX: 数据寄存器,用于乘除运算的默认操作数及存放 I/O 端口地址。
ESI / EDI: 源索引寄存器和目标索引寄存器,主要用于存放存储单元在段内的偏移量,也可用作通用寄存器。
ESP / EBP: 堆栈指针寄存器和基址指针寄存器,ESP 用于指向栈顶,EBP 通常用作函数调用的帧指针。
二、内存模型:堆(Heap)
程序运行的时候,操作系统会给它分配一段内存,用来储存程序和运行产生的数据。这段内存有起始地址和结束地址,比如从0x1000到0x8000,起始地址是较小的那个地址,结束地址是较大的那个地址。
程序运行过程中,对于动态的内存占用请求(比如新建对象,或者使用malloc命令),系统就会从预先分配好的那段内存之中,划出一部分给用户,这种因为用户主动请求而划分出来的内存区域,叫做 Heap(堆)
C语言中通过malloc或calloc来申请堆,通过free()释放,堆的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。
三、内存模型:栈(Stack)
Stack 是由于函数运行而临时占用的内存区域
栈是一种具有特定操作规则的数据结构,它遵循后进先出(LIFO,Last In First Out)的原则。栈有两个基本操作:
- 压栈(Push):将数据放入栈顶。
- 出栈(Pop):从栈顶移除数据。
栈的特点是操作非常高效,因为所有的操作都是在栈顶进行的,而且栈的大小通常是有限的,由系统或者语言的实现限制。
谈及栈就必定谈及栈帧,栈帧是栈的一个实际应用:栈帧是栈数据结构在函数调用和返回过程中的具体应用,用于存储函数调用时所需的局部变量、参数和执行状态信息。
再进行一个函数时,会依次先压入函数的参数(从右到左),返回地址后,创建栈帧,会在函数结束后会删除栈帧恢复堆栈。
四、x86汇编指令(Instructions)
mov指令
mov 指令将第二个操作数——
寄存器的内容、内存中的内容或常数值
,复制到第一个操作数——寄存器或内存
,但不能用于直接从内存复制到内存
lea指令
它不执行内存访问,仅计算地址偏移
push指令
push 指令将操作数压入内存的栈,常用于函数调用。
ESP 是栈顶
,压栈前先将 ESP 值减 4,然后将操作数压入 ESP 指示的地址,栈中元素固定为 32 位。pop指令
pop 指令
执行出栈
工作,出栈前先将 ESP 指示的地址种内容取出栈,然后将 ESP 值加 4add/sub 指令
add 指令将
两个操作数相加
,相加的结果保存到第一个操作数
中。sub 指令用于两个操作数相减
inc/dec 指令
imul指令
带符号整数乘法指令,有两种格式:1、两个操作数,将两个操作数相乘,并将结果保存在第一个操作数中,第一个操作数必须为寄存器;2、三个操作数,将第二个和第三个操作数相乘,并将结果保存在第一个操作数中,第一个操作数必须为寄存器
乘法结果可能溢出,则编译器溢出标志 OF =1,以使 CPU 调出溢出异常处理程序。
idiv指令
带符号整数除法指令,只有一个操作数,即除数,而被除数则为 edx:eax 中的内容,64 位整数;操作结果分为两部分:商和余数,商送到 eax,余数送到 edx
and/or/xor 指令
逻辑与、逻辑或、逻辑异或操作指令,用于操作数的位操作,操作结果放在第一个操作数中
not 指令
位翻转指令,将操作数的每一位翻转,即0⟶1,1⟶0
shl/shr 指令
逻辑位移指令,shr 为逻辑右移,shl 表示逻辑左移,第一个操作数表示被操作数,第二个操作数指示移位的位数
控制流指令
X86 处理器维持这一个指示当前执行指令的指令指针(IP),当执行一条指令后,此指针自动指向下一条指令。IP 寄存器不能直接操作,但可以用控制流指令更新。通常用标签(label)指示程序中的指令地址,在 X86 汇编代码中,可在任何指令前加入标签
jmp 指令
控制 IP 转移到 label 所指示的地址,从 label 中取出指令执行( jmp 用于无条件跳转)
call/ret 指令
call 指令首先将当前指令地址入栈,然后无条件转移到由标签指示的指令。与其他简单的跳转指令不同,call 指令保存调用之前的地址信息,当 call 指令结束后,返回调用之前的地址。ret 指令实现子程序的返回机制,ret 指令弹出栈中保存的指令地址,然后无条件转移到保存的指令地址执行。
__cdel(C调用约定)调用约定
在 C 语言中常用的调用约定,函数参数由调用者推入栈中,函数返回时清理栈,返回值通常通过寄存器传递(如 EAX)。
参数由调用者推入栈中,函数负责清理栈,返回值通过寄存器传递
示例
__stdcall调用约定
参数由调用者推入栈中,被调函数负责清理栈,返回值通过寄存器传递
在 Windows 平台上常用的调用约定,函数参数由调用者推入栈中,被调函数清理栈,返回值通常通过寄存器传递(如 EAX)。
- Author:Albert1x
- URL:https://albert-1x.top//article/x86%E6%B1%87%E7%BC%96%E7%AE%80%E4%BB%8B
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!