目录
CPU、寄存器、内存之间的关系
寄存器
通用寄存器
EAX寄存器
EBX寄存器
ECX寄存器
EDX寄存器
EBP寄存器
ESP寄存器
ESI寄存器
EDI寄存器
总结
段寄存器
分段内存管理机制
段与段寄存器
指令指针寄存器EIP
标志寄存器
内存
虚拟内存
大端存储与小端存储
CPU、寄存器、内存之间的关系
当你运行一个.exe的可执行文件时,CPU,寄存器,内存所发挥作用如下
提醒:寄存器是在CPU中的,在叙述时为了便于理解,就将二者分开做介绍。
CPU:是计算机的核心,负责执行程序指令和进行算术逻辑运算。它包含了多个执行单元,如控制单元、算术逻辑单元和数据缓存等。CPU从内存中读取指令,并按照指令的操作码执行相应的操作。它使用寄存器来存储和操作数据,控制程序的流程,并与其他系统组件进行协调。
寄存器:寄存器是CPU内部的一小块高速存储区域,用于存储临时数据、地址和控制信息。寄存器的访问速度非常快,比内存快得多。CPU使用寄存器来执行各种操作,包括算术运算、逻辑运算、内存地址计算和控制流程等。寄存器还用于存储函数的返回值、传递函数参数和保存中间结果等。
CPU和寄存器相互配合完成程序的执行,寄存器主要是辅助CPU,存储CPU从内存读取的指令,数据和暂时存储执行的结果等。
内存:内存是用于存储程序指令和数据的物理空间。程序的代码、变量、数组、堆栈等都存储在内存中。CPU通过读取和写入内存中的数据来执行程序。执行指令时,CPU从内存中读取指令,并将指令的操作数和地址存储在寄存器中进行处理。内存还用于存储程序运行时的动态分配的数据和堆栈帧。内存的访问速度相对较慢,但它可以提供大容量的存储空间。
内存的作用是存储程序指令和数据的仓库,供CPU读取和写入执行结果。
执行程序时,CPU负责控制和执行指令,使用寄存器进行数据操作和控制流程,而内存则存储程序指令和数据。
场景:当你运行一个程序时,会经历如下过程:
- 把程序的可执行文件加载进入内存,包括程序所需的数据,程序的指令等
- CPU通过不断地从内存中读取指令、读取和写入数据
- 使用寄存器进行数据操作和控制,来实现程序的功能
- 把指令执行的结果重新写入内存
总结:内存是一个大仓库存储指令数据;寄存器是个小仓库,存储CPU读取的指令数据,存储执行指令过程的临时结果,并且记录一些数据用于辅助程序执行流程控制。CPU则只负责执行程序指令执行和运算。
寄存器和内存都是为了存储,为什么要引入寄存器?
寄存器和内存都用于存储数据,但它们在计算机体系结构中扮演不同的角色,引入寄存器的主要目的是为了提高数据的访问速度和执行效率。以下是一些原因:
访问速度:寄存器位于CPU内部,与CPU之间的数据传输速度非常快,通常与CPU时钟速度相匹配。相比之下,内存的访问速度较慢,需要通过总线进行数据传输,而总线速度相对较慢。寄存器的高速访问速度使得CPU可以更快地存储和操作数据,提高了计算效率。
数据操作:寄存器提供了临时存储数据和中间结果的能力,使得CPU可以直接对寄存器中的数据进行操作,而无需频繁地访问内存。这减少了对内存的读写操作,提高了计算速度。寄存器还可以用于存储函数的返回值、函数参数传递和局部变量等,减少了对内存的频繁访问。
寄存器数量有限:相比之下,寄存器的数量相对较少。CPU的寄存器数量通常是固定的,并且有限。寄存器的数量和大小受到硬件设计的限制。因此,寄存器主要用于存储频繁使用的数据和控制信息,而不是存储大量的程序指令和数据。
综上所述,引入寄存器的目的是为了提高数据的访问速度和执行效率。寄存器作为位于CPU内部的高速存储区域,用于存储临时数据、地址和控制信息,以便CPU可以更快地存取和操作数据。寄存器的引入使得计算机能够更高效地执行程序指令和数据操作,提高计算性能和响应速度。
皇帝太监和大臣,古代上朝的时候,大臣如果想递奏折,需要先把奏折传给太监,然后再由太监传给皇 帝。CPU 就相当于皇帝,而寄存器就相当于太监,他可以直接把数据传送给皇帝,效率高但是数量少,内存 呢,就相当于大臣,速度慢,但是数量多。
接下来讲详细介绍寄存器和内存
寄存器
寄存器是计算机体系结构中的一种存储设备,位于处理器内部。它们用于临时存储和处理数据、指令和地址等信息,以支持计算机的运算和控制流操作。寄存器通常比内存访问更快,因为它们位于处理器芯片上,与处理器核心更近,可以更快地读取和写入数据。
我们需要关注通用寄存器,段寄存器,指令指针寄存器,标志寄存器
通用寄存器
通用寄存器是用于存储临时数据和中间结果的多个寄存器组。它们可以用于不同的目的,例如存储算术和逻辑操作的操作数、函数调用参数、局部变量等。通用寄存器在程序执行过程中可以频繁地读取和写入。
在x64dbg中,八个常用的寄存器如下所示
EAX寄存器
eax(Extended Accumulator)是x86架构中的通用寄存器之一。它是32位宽度的寄存器,可以用于存储数据和进行算术和逻辑操作。
eax寄存器在x86汇编语言中具有多种用途和功能:
-
累加器:eax寄存器经常被用作累加器,用于存储计算结果或参与算术运算。例如,可以使用eax寄存器进行加法、减法、乘法和除法等运算操作。
-
返回值:eax寄存器通常用于存储函数调用的返回值。当调用函数执行完毕后,返回的结果可以存储在eax寄存器中,以便供调用函数继续使用。
-
数据传输:eax寄存器可以用于数据传输操作,从内存或其他寄存器中加载数据到eax寄存器,或将eax寄存器中的数据存储到内存或其他寄存器中。
-
比较和条件判断:eax寄存器经常与比较指令一起使用,用于比较两个值的大小或进行条件判断。比较结果会影响条件跳转指令的执行,根据比较结果决定程序的执行路径。
-
位操作:eax寄存器可以用于位操作,如逻辑与、逻辑或、位移和位掩码等。这些操作可以对eax寄存器中的数据进行位级操作,实现特定的位操作需求。
eax寄存器是x86架构中的一个重要寄存器,常用于存储临时数据、执行算术逻辑操作和处理函数调用的返回值。
EBX寄存器
ebx(Extended Base Register)是x86架构中的通用寄存器之一。它是32位宽度的寄存器,用于存储数据和进行地址计算。
ebx寄存器在x86汇编语言中具有多种用途和功能:
-
基址寄存器:ebx寄存器经常被用作基址寄存器,用于存储基地址或数组的起始地址。通过在ebx寄存器中保存基址,可以实现对数组、结构体和其他数据结构的访问和操作。
-
数据传输:ebx寄存器可以用于数据传输操作,从内存或其他寄存器中加载数据到ebx寄存器,或将ebx寄存器中的数据存储到内存或其他寄存器中。
-
地址计算:ebx寄存器可用于执行地址计算,例如通过加法或减法操作将偏移量添加到基址上,以计算目标地址。这在访问数据结构的不同成员或数组元素时很有用。
-
存储局部变量:ebx寄存器可以被分配用于存储局部变量,这在一些编程模型中是常见的做法。然而,需要注意的是,在函数调用期间,ebx寄存器的值可能会被破坏,因此需要在必要时保存和恢复它的值。
-
保留寄存器:在一些编程约定中,ebx寄存器可能被保留作为某些操作的临时寄存器或作为函数调用的保留寄存器。在这种情况下,使用ebx寄存器之前需要确保其值不会被破坏。
总之,ebx寄存器是x86架构中的一个通用寄存器,用于存储数据和执行地址计算。它经常被用作基址寄存器,用于访问数组和数据结构。
ECX寄存器
ecx(Extended Counter Register)是x86架构中的通用寄存器之一。它是32位宽度的寄存器,常用于循环计数和存储临时数据。
ecx寄存器在x86汇编语言中具有多种用途和功能:
-
循环计数器:ecx寄存器经常被用作循环计数器,用于控制循环的执行次数。在循环指令(如loop)中,ecx寄存器的值会被递减,直到为零,从而控制循环的终止。
-
数据传输:ecx寄存器可以用于数据传输操作,从内存或其他寄存器中加载数据到ecx寄存器,或将ecx寄存器中的数据存储到内存或其他寄存器中。
-
存储临时数据:ecx寄存器可以用于存储临时数据,在计算过程中进行中间结果的保存。它可以作为一个通用寄存器,用于执行各种算术和逻辑操作。
-
字符串操作:ecx寄存器在字符串操作中经常被使用,例如字符串的复制、比较和搜索等。它通常与edi寄存器(目的地址寄存器)一起使用,用于指定字符串操作的长度。
-
保留寄存器:在一些编程约定中,ecx寄存器可能被保留作为某些操作的临时寄存器或作为函数调用的保留寄存器。在这种情况下,使用ecx寄存器之前需要确保其值不会被破坏。
总之,ecx寄存器是x86架构中的一个通用寄存器,用于循环计数、存储临时数据和执行数据传输操作。
EDX寄存器
edx(Extended Data Register)是x86架构中的通用寄存器之一。它是32位宽度的寄存器,用于存储数据和执行各种操作。
edx寄存器在x86汇编语言中具有多种用途和功能:
-
数据传输:edx寄存器可以用于数据传输操作,从内存或其他寄存器中加载数据到edx寄存器,或将edx寄存器中的数据存储到内存或其他寄存器中。
-
存储临时数据:edx寄存器可以用于存储临时数据,在计算过程中进行中间结果的保存。它可以作为一个通用寄存器,用于执行各种算术和逻辑操作。
-
基址寄存器:在某些情况下,edx寄存器可以用作基址寄存器,存储基地址或数组的起始地址。通过在edx寄存器中保存基址,可以实现对数组、结构体和其他数据结构的访问和操作。
-
输入/输出端口:在与外部设备进行输入/输出操作时,edx寄存器常用于指定要读取或写入的端口号。
-
保留寄存器:在一些编程约定中,edx寄存器可能被保留作为某些操作的临时寄存器或作为函数调用的保留寄存器。在这种情况下,使用edx寄存器之前需要确保其值不会被破坏。
总之,edx寄存器是x86架构中的一个通用寄存器,用于存储数据和执行各种操作。它可用于数据传输、存储临时数据、作为基址寄存器和进行输入/输出端口操作。
EBP寄存器
EBP(Extended Base Pointer)是x86架构中的寄存器之一,也被称为基址指针寄存器或帧指针寄存器。它用于在函数调用期间管理堆栈帧。
EBP寄存器在x86汇编语言中具有以下主要功能:
-
帧指针:EBP寄存器通常用作当前函数的帧指针,指向当前函数的堆栈帧的底部。堆栈帧包含了函数的局部变量、参数和其他与函数执行相关的信息。
-
访问局部变量和参数:通过EBP寄存器可以访问函数的局部变量和参数。使用相对于EBP的偏移量,可以在堆栈中找到局部变量和函数参数的存储位置。
-
函数调用:在函数调用期间,EBP寄存器用于保存上一个函数的EBP值,以便在函数返回后恢复正确的堆栈帧。这样可以实现函数调用的嵌套和正确的堆栈管理。
-
动态链:EBP寄存器在堆栈帧中还可以用于建立动态链。动态链是用于访问外部作用域的变量和数据的指针链。
需要注意的是,EBP寄存器在函数调用过程中的值会被改变,因此在使用EBP寄存器之前,需要保存其值以免丢失。一般情况下,EBP寄存器的值会在函数开头通过指令push ebp
保存,并在函数结束时通过指令pop ebp
恢复。
总而言之,EBP寄存器在x86汇编中用于堆栈帧的管理和访问局部变量和参数。它在函数调用中起着重要的作用,并帮助实现正确的堆栈操作和访问函数作用域内的数据。
ESP寄存器
ESP(Extended Stack Pointer)是x86架构中的寄存器之一,也被称为堆栈指针寄存器。它用于管理程序的堆栈操作。
ESP寄存器在x86汇编语言中具有以下主要功能:
-
堆栈指针:ESP寄存器指向当前堆栈顶部的位置,即栈指针。堆栈用于存储函数调用期间的局部变量、参数、返回地址和其他临时数据。通过调整ESP寄存器的值,可以在堆栈中分配和释放内存空间。
-
函数调用:在函数调用期间,ESP寄存器用于分配空间以存储局部变量和其他函数调用所需的数据。通过将ESP寄存器的值减小,可以在堆栈上为局部变量分配内存空间。
-
数据压栈和出栈:ESP寄存器用于压入数据到堆栈和从堆栈中弹出数据。通过递增或递减ESP寄存器的值,可以实现数据的入栈和出栈操作。
-
堆栈操作:ESP寄存器与EBP寄存器一起协作,用于正确管理堆栈的状态和帧指针。EBP寄存器指向当前函数的堆栈帧的底部,而ESP寄存器指向堆栈的顶部。通过调整ESP寄存器的值,可以在堆栈中添加或移除堆栈帧。
需要注意的是,ESP寄存器的值会随着堆栈操作的进行而变化。在进行函数调用、压栈和出栈操作时,必须保持ESP寄存器的值正确,以免造成堆栈的混乱和错误的数据访问。
总而言之,ESP寄存器在x86汇编中用于管理程序的堆栈操作。它指向堆栈顶部的位置,用于分配和释放内存空间、函数调用和数据的入栈和出栈操作。
ESI寄存器
ESI(Extended Source Index)是x86架构中的寄存器之一,也被称为源索引寄存器。它是32位宽度的寄存器,主要用于字符串和数组操作。
ESI寄存器在x86汇编语言中具有以下主要功能:
-
字符串操作:ESI寄存器经常与EDI寄存器(目的索引寄存器)一起使用,用于字符串操作,例如字符串的复制、比较和搜索等。ESI寄存器用于存储源字符串的地址。
-
数组访问:ESI寄存器可以用于数组访问,用于存储数组的基址或起始地址。通过ESI寄存器可以实现对数组元素的遍历和操作。
-
数据传输:ESI寄存器可以用于数据传输操作,从内存或其他寄存器中加载数据到ESI寄存器,或将ESI寄存器中的数据存储到内存或其他寄存器中。
-
循环操作:ESI寄存器经常被用作循环计数器,用于控制循环的执行次数。在循环指令(如rep、repe、repne)中,ESI寄存器的值会被递减或递增,从而控制循环的终止。
-
保留寄存器:在一些编程约定中,ESI寄存器可能被保留作为某些操作的临时寄存器或作为函数调用的保留寄存器。在这种情况下,使用ESI寄存器之前需要确保其值不会被破坏。
需要注意的是,ESI寄存器在进行字符串和数组操作时的值会发生变化,因此在使用ESI寄存器之前,需要保存其值以免丢失。一般情况下,在进行字符串和数组操作之前,可以通过将ESI寄存器的值保存到其他寄存器或内存中,以便后续恢复或使用。
总而言之,ESI寄存器在x86汇编中用于字符串和数组操作。它用于存储源字符串的地址、数组的基址或起始地址,以及作为循环计数器和数据传输的临时寄存器。
EDI寄存器
EDI(Extended Destination Index)是x86架构中的寄存器之一,也被称为目的索引寄存器。它是32位宽度的寄存器,主要用于字符串和数组操作。
EDI寄存器在x86汇编语言中具有以下主要功能:
-
字符串操作:EDI寄存器经常与ESI寄存器(源索引寄存器)一起使用,用于字符串操作,例如字符串的复制、比较和搜索等。EDI寄存器用于存储目标字符串的地址。
-
数组访问:EDI寄存器可以用于数组访问,用于存储数组的基址或起始地址。通过EDI寄存器可以实现对数组元素的遍历和操作。
-
数据传输:EDI寄存器可以用于数据传输操作,从内存或其他寄存器中加载数据到EDI寄存器,或将EDI寄存器中的数据存储到内存或其他寄存器中。
-
循环操作:EDI寄存器经常被用作循环计数器,用于控制循环的执行次数。在循环指令(如rep、repe、repne)中,EDI寄存器的值会被递减或递增,从而控制循环的终止。
-
保留寄存器:在一些编程约定中,EDI寄存器可能被保留作为某些操作的临时寄存器或作为函数调用的保留寄存器。在这种情况下,使用EDI寄存器之前需要确保其值不会被破坏。
需要注意的是,EDI寄存器在进行字符串和数组操作时的值会发生变化,因此在使用EDI寄存器之前,需要保存其值以免丢失。一般情况下,在进行字符串和数组操作之前,可以通过将EDI寄存器的值保存到其他寄存器或内存中,以便后续恢复或使用。
总而言之,EDI寄存器在x86汇编中用于字符串和数组操作。它用于存储目标字符串的地址、数组的基址或起始地址,以及作为循环计数器和数据传输的临时寄存器。
总结
- EAX主要作用是操作数和累加器
- EBX主要作用是指向Data Segment数据
- ECX主要作用是字符串和循环操作计数器
- EDX主要作用是指向输入输出设备的端口号,IO指针
- EBP与ESP配合使用通用做管理函数调用时堆栈操作
- ESI主要作用是配合EDI操作字符串,指向DS寄存器指向的数据
- EDI主要作用是操作字符串,作为基址访问数组,循环计数器
需要关注两方面:
- 调用函数时程序的堆栈操作,每当调用函数就会新起一个栈帧,ESP指向栈顶,EBP指向栈底部
- 字符串相关操作,ESI指向字符串源地址,EDI指向字符串目的地址,ECX指定字符串的长度
这些寄存器都有自己的特性,但是他们有再多的特性,也可以做其他的事情。除了ESP不能随意修改, 因为它指向栈顶,其它寄存器可以任意使用。
段寄存器
段寄存器是一种特殊的寄存器,存在于一些计算机体系结构中,如x86体系结构。段寄存器用于存储内存访问的段(segment)信息,它们与分段内存管理机制紧密相关。
分段内存管理机制
分段内存管理机制是一种早期的内存管理方式,在一些计算机体系结构中使用。它将内存划分为多个不同大小的段(segments),每个段具有固定的起始地址和长度。段寄存器用于存储当前正在访问的段的信息,例如段的起始地址,以便计算出最终的物理地址。分段内存管理的主要目的是提供对内存的逻辑划分,以便更好地组织和管理程序的代码和数据。
段与段寄存器
每个段代表了一个逻辑上相关的数据集合,例如代码段、数据段、堆栈段等。每个段由一个起始地址和一个长度来定义。
为了使用分段内存管理,计算机体系结构通常提供了特殊的段寄存器,用于存储当前正在访问的段的信息。
常见的段寄存器包括:代码段寄存器,数据段寄存器,堆栈段寄存器,附加段寄存器
在x64dbg中,可以看到段寄存器是16位的,两个字节
在x86体系结构中,有以下几个常见的段寄存器:
-
代码段寄存器(Code Segment Register,通常为CS):存储当前正在执行的指令所在的代码段的起始地址。
-
数据段寄存器(Data Segment Register,通常为DS):存储当前正在访问的数据段的起始地址。
-
堆栈段寄存器(Stack Segment Register,通常为SS):存储当前正在使用的堆栈段的起始地址。
-
附加段寄存器(Extra Segment Registers,如ES、FS、GS):用于存储其他附加段的起始地址,这些段通常用于特定的用途,如字符串操作、线程局部存储等。
指令指针寄存器EIP
里面保存的是下一条要执行的指令。
需要关注CS:IP取指令的问题。
标志寄存器
标志寄存器(Flags Register)是计算机体系结构中的一种特殊寄存器,用于存储运算结果的状态信息,例如条件判断、算术运算溢出、零值等。标志寄存器中的每个位(或标志位)都代表了不同的状态标志,这些标志位的值可以被处理器使用,以便进行条件分支、错误处理和其他操作。
这个寄存器又32位,它的使用并不是整体使用,而是按照每一位进行使用。
在x64dbg中显示常用的9位
关于每一位的作用暂时不需要了解特别清楚,每一位的用法和汇编息息相关,等到学习汇编的时候再做详细了解。
内存
内存主要要出当前正在运行程序所需的指令和数据
虚拟内存
32位程序,每个应用程序都有4GB的内存空间
这里的内存是虚拟内存,并不是真实的4GB。虚拟内存到真实的物理内存之间还有一层映射关系
4GB大小的由来:
32位寄存器能表示的最大的值就是0xFFFFFFFF,实际上还要在+1,因 为0也是一个值
2^32 / 1024 / 1024 / 1024 = 2^32 / 2^30 = 2*2 =4GB
这就是为什么32位系统每个应用程序都有4GB的内存空间。4GB的内存空间很大,那么怎么管理这一片 内存呢? 那么就需要给每一个空间分配一个地址。比如第一个地址我给他起一个编号00000000,然后依次往后 排列,最大的地址是0xFFFFFFFF。
这些给内存起的编号,就是内存地址。我们可以通过这些内存编号往内存地址里面存值,也可以通过内 存地址从里面取值。
大端存储与小端存储
大段存储:数值的高位字节存放在内存的低地址端,低位字节存放在内存的高地址端
小端存储:即低位字节放在内存的低地址端,高位字节放在内存的高地址端。
在汇编学习中,最重要的就是,寄存器,内存,堆栈这三个概念,学会了这三个就等于学会了汇编,当前只是粗浅了解了相关的概念和作用,他们的具体作用还是要在学习汇编过程中逐渐加深。