ARM 体系架构及其工作原理_arm架构原理-程序员宅基地

技术标签: CPU工作原理  嵌入式、物联网开发  ARM  

架构的演变历史

我们首先介绍 ARM Ltd,这里先说的是公司而不是架构。ARM 的发展历史非常久远,超乎许多人的想象。

首先,我们提供一些背景信息,ARM 成立于20世纪90年代末,从另一家位于剑桥的公司分拆而来,那家公司叫做 Acorn Computers,曾经是英国教育市场的著名个人台式计算机供应商,现已不复存在。

80年代中期时,Acorn 一个小团队接受了一个挑战,为他们的下一代计算机挑选合适的处理器,他们起草了一个技术需求说明书,经过相当长的摸索后得出一个结论:无法找到与之相符的产品,于是 Acorn 决定自己设计处理器,一个小团队只用了18个月就完成了设计并实现了这款处理器。

1985年4月26日,第一台原型机在 Acorn 的剑桥办公室中开始运行代码,那时它被称为”Acorn RISC Machine”,随着 Acorn 公司转向衰落,处理器设计部门被分了出来,组成了一家新公司,最初叫做 Advanced RSIC Machines Ltd。现在公司和处理器都简称为ARM。

ARM 以其各种 RISC 处理器内核而著称,但也出品大量的支持技术满足芯片设计师和软件开发者的需要,这包括物理IP,软件模型和开发工具,图形处理器,以及外围设备,注意,但是 ARM 并不生产芯片,ARM是半导体知识产权业务中的开拓先锋,目前市面上大量 ARM 设备都是由ARM分布于世界各地的授权商制造的。

下面说下 ARM 产品在哪些领域通过通用数字产品发挥用武之地,ARM 提供:在系统芯片(SoC)上的系统级IP,以及物理IP,确保其可制造性开发工具,帮助设计和制造系统架构和软件,当然生产出成品还需要许多其他投入,如工业设计,封装,环境调查,操作系统,外围IP等,这些都不是 ARM 的产品,但 ARM 有很多合作伙伴,制造出了成千上万的设备,从下图中你会发现许许多多部署了基于 ARM 解决方案的应用。

0?wx_fmt=png

从硬盘驱动器到打印机,从游戏设备到智能量表,从洗衣机到电视机,可谓包罗万象,即便如此,还没有终点,时刻都在增长,到目前为止,以ARM架构的芯片出货量总共达到500亿片,每年还以大约80亿的数字在增长,到2020年,总量有望达到1000亿。

ARM 内核现在广受欢迎的一个原因是支持一系列的性能和功能点。我相信许多人听说 ARM 是从 ARM7TDMI 处理器内核的成功开始的,从上世纪90年代起这一内核在手机行业得到了广泛采用,也是ARM早期成功的奠基石。

虽然现在依然受到广泛使用,也可以购买到包含这一内核的大量部件,但不再提供 ARM7TDMI 的授权许可,现在已经从这一内核发展出以实时嵌入式空间为目标的整个产品路线图,现在有两大产品系列,Cortex-M系列主要用于注重成本节约的微控制器;

Cortex-R系列,提供非常高的性能和吞吐量,同时保持精准的时序属性和可预测的中断延时,通常用于时序关键的应用中,如引擎管理系统和硬盘驱动器控制器。

后来发展了整个系列的应用处理器,从产品线最初的ARM926EJ-S开始,发展到了 ARM11MP,现在包含了 Cortex-A 系列,这些处理器设计为可在要求 linux 等平台操作系统的应用中提供可缩放的高性能。

它们融合了精密的内存管理功能,以及多媒体处理扩展指令集,从 ARM11MP 开始加入了针对多核系统的支持,Cortex-A 系列的最新核心现在以多核配置提供,这使得它们能够真正涵盖广阔的功率和性能点范围。

我们现在已经对公司渊源和架构有了些了解,现在让我们进入 ARM 芯片的内部吧。

内核的工作原理

0?wx_fmt=png

经典的ARM系统级芯片或所谓的SocC包含许多组件,其中只有一些直接源自ARM。首先,核心本身通常深度嵌入在设备内部,在设备范畴内通常不直接可见,而调试端口通常是唯一和核心本身相连的外露部分,有一些粘合逻辑,如时钟和复位集成电路。

由于 ARM 核心只有两个中断输入,最常见的外设就是某种中断控制器,在外设内部,各组件通过芯片上互联总线架构相互连接,对于极大多数基于ARM的设备而言,这就是标准的 AMBA 互联。

AMBA 指定了两个总线,称为AXI的高性能系统总线,和称为APB的低功耗外设总线,APB通常用于连接所有外设,AXI则用于存储器和其他发高速设备,大多数设备都有一定数量的芯片上存储以及连接外设存储器设备的接口,但是注意,与设备的外部连接并不是AMBA总线,这仅在设备内部使用,并不外露。

下面看看这个Soc的工作原理——编程器模型(programmer’s model)。谨记,A系列和R系列配置在编程器模型上非常相似,但M系列配置在许多非常重要的方面都有很大不同,这在接下来的讲解中会指出这些差别。

从根本上说,ARM是RISC架构,你可能会否认现在的ARM内核其实不属于RISC平台,但它们与RISC有很大的渊源,也保留了传统上与RISC架构相关的许多特性,例如大多数指令在一个周期内执行,寄存器集基本上是正交的,而且指令集实施加载存储式架构,也就意味着能够直接处理内存中内容的指令只有加载和存储指令,如果需要对内存中的值执行任何处理,程序必须将这些值加载到寄存器中,执行所需的处理,然后将结果存回到内存中,其他常见架构则能够直接操控或修改内存中的内容。

所有的内部寄存器除了一些受到NEON架构的矢量处理功能支持外都是32位宽的,它们的内部由32位ALU处理,内存则通常在32位元中予以处理,这就是ARM的字长。

谈到指令集时,你会发现 ARM 核心不只有一个指令集,所有 ARMv7-A 和 ARMv7-R 核心都支持32位原生 ARM 指令集和 Thumb 指令集,后者中的指令可以是32位或者16位的。

ARM 指令集释放了内核的完整性能潜力,而Thumb指令集则提供了更出色的代码密度,我们把ARM和Thumb指令间切换这一过程称为“交互工作”,不要担心,编译器和链接器会处理它们。一些较旧的内核支持Thumb指令集的早期版本,其中所有的指令都是16位指令,比如 ARMv7-M 内核仅就支持Thumb指令集。

如果你之前接触过处理器架构,相信你会熟悉运行模式的概念以及特权的概念。许多架构通常支持两种模式,分别为“Supervisor”和“User”,其中一个模式拥有特权,另一个则没有。

在无特权模式下代码可能无法直接执行某些特定的操作,比如,禁用中断,重新配置内存保护,或访问特定的内存区域,这是大多数操作系统的基本要求,允许系统从用户任务中保护自己。ARM内核通常支持七种基本运行模式,每种模式有权访问自己的堆栈空间,以及一组不同的寄存器子集,除一个外其余都是由特权的模式,如下:

0?wx_fmt=png

其中6种是特权模式,User 模式是没有特权的模式,作为唯一的无特权模式,User 模式供操作系统用于用户任务和处理器。

此外,有5种模式称为“异常模式”,每一种都与处理特定种类的异常或中断相关,例如,当内核开始处理外部中断时会自动进入 IRQ 模式,而 Supervisor 模式则用于处理 SVC 指令和硬件复位,这些模式分别拥有专属的堆栈空间,以及一小组专用寄存器,我们把这一功能叫做寄存器编组,只是这些异常属于不同的类型。

注意,上图仅适用于 Cortex-A 和 Cortex-R 处理器,Cortex-M 微控制器的模式结构则全然不同。ARMv7-M 架构配置仅定义了两种模式,如下图,分别是 Thread 模式和 Handler 模式,Thread 模式没有特权,用于应用程序代码, Handler 模式有特权,用于异常处理程序,当系统复位时在 Thread 模式中开始执行,遇到异常时自动变为 Handler 模式,处理程序完成后再回到 Thread 模式。

0?wx_fmt=png

下面我们重点讲下这些模式是如何与寄存器组交互工作的:

0?wx_fmt=png

比如我们来看看核心切换到IRQ模式以处理外部异常时会发生什么,从图中你可以看到User模式的r13和r14切换为IRQ模式中与它们对应的寄存器,由于r13用作堆栈指针,所以这表示IRQ中断在独立的堆栈中进行处理。

此外也可以看到另一个寄存器也加入到集合中来,它是 Saved Program Status Register 即 SPSR,用于保留模式更改发生时处理器状态的快照,才能使得在处理中断事件后返回到 User 模式并恢复程序变得非常容易,当中断处理结束后,就回到User模式,重新获取原先的寄存器。

在以上描述的寄存器集合和组织适用于 Cotex-M 之外的所有ARM内核,Cotex-M 内核具有不同的寄存器集合和组织,见下图。

之前一直强调Cotex-M寄存器是不同的,差别就在这里,只有18个寄存器没有我们在其他内核上看到的编组方案。

首先,有13个通用寄存器,其中r0到r7是低位寄存器,r8 到 r12 是高位寄存器,还有3个特殊寄存器:Stack Pointer,Link Register 和 Program Counter,最后一个寄存器是程序状态寄存器 xPSR。

注意,Contex-M 内核有两种处理器模式:Thread 模式和 Handler 模式,只有一个寄存器在这两种模式之间编组,它就是 Stack Pointer。

0?wx_fmt=png

这里扩展下状态寄存器 Program status register:

0?wx_fmt=png

左边28到31位是ALU条件代码,由数据处理指令进行可选设置,并由条件指令进行测试,还有4个额外的状态位GE位,用于记录来自SIMD指令的多个结果。只有这些ALU状态位可以在处于User模式时进行修改。

最右边的5位显示当前的处理器模式,它们在响应异常中出现模式更改时自动设置,也可以手动修改以便在程序控制下更改模式。

J和T这两个位记录处理器的当前状态,告诉内核当前正在执行哪一行指令集,可能是ARM状态,即正在执行ARM指令;Thumb状态,即正在执行Thumb指令;或者Jazelle状态,即正在执行Java字节代码。

I位和F位可启用或禁用IRQ和FIQ中断。A位允许禁用或暂时停用异步数据中止。E位允许在程序控制下动态更改数据接口的字节序(Little或Big字节序),简化了混合字节序数据的处理。剩余的位被“保留”或者用于和特定指令的内部系统状态,不可由程序修改。

下面来讲一下 Cortex-M 内核中可用的状态寄存器:

0?wx_fmt=png

你会发现它比前面讲的状态寄存器简单的多,这也说明了Cortex-M内核的简洁性。有一个T位,因为 Cortex-M 内核仅支持 Thumb 指令集,所以此位始终是1。最后又一个字段,它在核心执行异常处理程序时包含当前活动的异常编号。

初学者可能会问异常时会发生什么,在ARM架构中,异常是某种类型的事件,导致任何内容正常的程序流中出现中断,异常可以是内部的,如内存转译错误;也可以是外部的,如来自外设的中断;也可以是同步的,如SVC指令;或者是异步的,如计时器中断。无论原因如何,核心对所有异常的处理方式基本上相同。

当一个应用程序在逐一执行各个指令时,异常来时内核要做的第一件事就是确保它能够在异常之后回到这一点上,为此我们必须对当前状态抓取一个快照,所以内核复制 CPSR 并保存在 SPSR 中,再复制PC并保存在LR中,然后内核切换到相应的异常模式禁用进一步的中断,确保它处于正确的状态,接着使用矢量表确定可以找到异常处理程序的位置,每一个异常类型分别有一个条目,每一条目是一个指令,分出相关的处理程序代码,所以核心就是从正确的矢量表条目加载 Program Counter 执行异常处理程序。

当处理程序完成时,要返回到中断的程序就简单了,只要从SPSR中保留的副本还原CPSR,再从链接寄存器还原 Program Counter。当然Cortex-M在处理异常时完全是另一回事,这里就不详讲了。

现在相信你已经了解了寄存器,模式和状态的所有信息,现在我们来谈谈ARM内核提供的指令集。目前市场上的大多数ARM内核至少支持两种指令集:原生的32位 ARM 指令集,以及混合了16位和32位的Thumb指令集,我们先看看ARM指令集。

虽然这次chat不是ARM汇编语言的课程,但也能让你有足够的了解。ARM指令集中的所有指令都是32位长,乍一看ARM指令的语法似乎非常复杂,不过一旦你了解运算符和可能的运算对象的基本结构,其实还是非常简单的,毕竟它是RISC架构。下面举例说明,第一个真的很简单:

  1. SUB r0, r1, #5
    它显然是个减法指令,有3个参数。第一个参数是寄存器,指定减法结果的目的地;另外两个参数指定输入参数,可以理解为从左到右为”r0 = r1 - 5”。

  2. ADD r2, r3, r3, LSL #2
    这是一个加法指令,提供一个作为第二输入运算对象的寄存器,再指定内联移动或循环运算应用到运算对象上,作为指令的一部分,这个指令可以理解为”r2等于r3加上r3向左移动两个位置”。

  3. ANDS r4, r4, #0x20
    这是一个逻辑AND指令,注意这个AND有个后缀’S’,这指定将CPSR中的ALU条件代码设为反映该结果,ARM数据处理运算默认情况下不影响条件代码,所以使用这个’S’后缀来指定需要这么做的运算。

  4. ADDEQ r5, r5, r6
    这又是一个ADD,它是有条件指令,该助记符带有“EQ”后缀,表明只有在达到EQ条件为真时才会执行这一指令,如果该条件不为真,指令将表现为NOP。

  5. LDR r0, [r1]
    这是一个加载指令,将r1中指定地址的值加载到r0中。在指定内存访问指令的地址时,我们使用方括号来表达。

  6. STRNEB r2, [r3, r4]
    这是存储指令,只有在NE条件有效时才会执行操作,其次它是一个字节层面的存储,它将r2中最不重要的字节存储到r3加r4得到的内存位置上。

目前为止,我们只是谈了 ARM 指令集,众所周知所有 ARM 指令都是32位的,为了提供更好的代码密度,ARM在很久之前推出了第二指令编码,叫做 Thumb, Thumb 所有指令都是16位的。

Thumb 代码通常在代码密度上可以改善大约35%,大多数C和C++代码都针对具备 Thumb 功能的核心上的 Thumb 进行编译。

既然 Thumb 这么好,我们为何要把真么多精力放在ARM指令集上呢?这是因为 Thumb 是编译代码的最佳目标,如果你直接在汇编程序中编写代码,ARM相对是更好的选择。下面让我们进一步地剖析ARM的实现原理。

ARM 的技术实现

要想深入理解ARM的实现原理是个很大的学习工程,这里一样希望读者读后能对ARM起到一个总体的认识,后续可以进一步的深入学习。我们先以 ARM 汇编基础来展开这一章的 chat。

汇编语言是机器代码上的一个薄的语法层,它由以二进制编码的指令组成,这是我们的计算机所理解。那么为什么我们不写代码呢?可想而知以二进制来进行 coding 的话是多么的痛苦,因此我们将编写ARM程序集。

但是计算机本身只识别机器码是不能运行汇编代码的,这就需要将汇编代码装到机器代码中的工具 GNU Binutils 项目中的 GNU Assembler。一旦用扩展名*.s编写程序就需要把它与其进行组合并与ld链接起来:

 

$ as program.s -o program.o$ ld program.o -o program

0?wx_fmt=gif

我们从最底层来看下,在最底层,电路上有电信号,信号是将电压切换为两个电平来形成的,例如0伏(关)或5伏(开)。

因为只是我们不能轻易的告诉电路电压,只能选择使用1/0来写入开/关的模式,然后我们对0和1的顺序进行分组,以形成机器码指令,该指令是计算机处理器的最小工作单元,以下是机器语言的示例:

 

   1110 0001 1010 0000 0010 0000 0000 0001

我们知道ARM处理器只能对寄存器执行数据处理,所以与存储器的交互有两种:从存储器加载到寄存器,并将值从寄存器存储到存储器,即ARM使用加载/存储(LDR和STR)模型进行内存访问。

通常 LDR 用于将内存中的内容加载到寄存器中,STR用于存储寄存器中的内容到存储器地址。我们来举一个基本例子:

0?wx_fmt=png

第一看的小伙伴或许会一头雾水,下面以一张动态图来解释下 ARM 是如何和存储器交互的:

0?wx_fmt=gif

参考

正如刚开始所说的,本次 chat 不是所有 ARM 架构和技术的详尽概览,而是通向 ARM 世界的一扇大门,ARM 网站上有丰富的文档等你去查阅,探索。

比如(http://infocenter.arm.com)可以找到架构参考手册,知识库文章,常见问题解答,处理器文档,以及开发者指南等。

ARM 还有一个不断壮大的全球大学计划,为你提供大量的教学和培训资源,软件工具,以及硬件开发板。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ChenGuiGan/article/details/103336986

智能推荐

C#连接OPC C#上位机链接PLC程序源码 1.该程序是通讯方式是CSharp通过OPC方式连接PLC_c#opc通信-程序员宅基地

文章浏览阅读565次。本文主要介绍如何使用C#通过OPC方式连接PLC,并提供了相应的程序和学习资料,以便读者学习和使用。OPC服务器是一种软件,可以将PLC的数据转换为标准的OPC格式,允许其他软件通过标准接口读取或控制PLC的数据。此外,本文还提供了一些学习资料,包括OPC和PLC的基础知识,C#编程语言的教程和实例代码。这些资料可以帮助读者更好地理解和应用本文介绍的程序。1.该程序是通讯方式是CSharp通过OPC方式连接PLC,用这种方式连PLC不用考虑什么种类PLC,只要OPC服务器里有的PLC都可以连。_c#opc通信

Hyper-V内的虚拟机复制粘贴_win10 hyper-v ubuntu18.04 文件拷贝-程序员宅基地

文章浏览阅读1.6w次,点赞3次,收藏10次。实践环境物理机:Windows10教育版,操作系统版本 17763.914虚拟机:Ubuntu18.04.3桌面版在Hyper-V中的刚安装好Ubuntu虚拟机之后,会发现鼠标滑动很不顺畅,也不能向虚拟机中拖拽文件或者复制内容。在VMware中,可以通过安装VMware tools来使物理机和虚拟机之间达到更好的交互。在Hyper-V中,也有这样的工具。这款工具可以完成更好的鼠标交互,我的..._win10 hyper-v ubuntu18.04 文件拷贝

java静态变量初始化多线程,持续更新中_类初始化一个静态属性 为线程池-程序员宅基地

文章浏览阅读156次。前言互联网时代,瞬息万变。一个小小的走错,就有可能落后于别人。我们没办法去预测任何行业、任何职业未来十年会怎么样,因为未来谁都不能确定。只能说只要有互联网存在,程序员依然是个高薪热门行业。只要跟随着时代的脚步,学习新的知识。程序员是不可能会消失的,或者说不可能会没钱赚的。我们经常可以听到很多人说,程序员是一个吃青春饭的行当。因为大多数人认为这是一个需要高强度脑力劳动的工种,而30岁、40岁,甚至50岁的程序员身体机能逐渐弱化,家庭琐事缠身,已经不能再进行这样高强度的工作了。那么,这样的说法是对的么?_类初始化一个静态属性 为线程池

idea 配置maven,其实不用单独下载Maven的。以及设置新项目配置,省略每次创建新项目都要配置一次Maven_安装idea后是不是不需要安装maven了?-程序员宅基地

文章浏览阅读1w次,点赞13次,收藏43次。说来也是惭愧,一直以来,在装环境的时候都会从官网下载Maven。然后再在idea里配置Maven。以为从官网下载的Maven是必须的步骤,直到今天才得知,idea有捆绑的 Maven 我们只需要搞一个配置文件就行了无需再官网下载Maven包以后再在新电脑装环境的时候,只需要下载idea ,网上找一个Maven的配置文件 放到 默认的 包下面就可以了!也省得每次创建项目都要重新配一次Maven了。如果不想每次新建项目都要重新配置Maven,一种方法就是使用默认的配置,另一种方法就是配置 .._安装idea后是不是不需要安装maven了?

奶爸奶妈必看给宝宝摄影大全-程序员宅基地

文章浏览阅读45次。家是我们一生中最重要的地方,小时候,我们在这里哭、在这里笑、在这里学习走路,在这里有我们最真实的时光,用相机把它记下吧。  很多家庭在拍摄孩子时有一个看法,认为儿童摄影团购必须是在风景秀丽的户外,即便是室内那也是像大酒店一样...

构建Docker镜像指南,含实战案例_rocker/r-base镜像-程序员宅基地

文章浏览阅读429次。Dockerfile介绍Dockerfile是构建镜像的指令文件,由一组指令组成,文件中每条指令对应linux中一条命令,在执行构建Docker镜像时,将读取Dockerfile中的指令,根据指令来操作生成指定Docker镜像。Dockerfile结构:主要由基础镜像信息、维护者信息、镜像操作指令、容器启动时执行指令。每行支持一条指令,每条指令可以携带多个参数。注释可以使用#开头。指令说明FROM 镜像 : 指定新的镜像所基于的镜像MAINTAINER 名字 : 说明新镜像的维护(制作)人,留下_rocker/r-base镜像

随便推点

毕设基于微信小程序的小区管理系统的设计ssm毕业设计_ssm基于微信小程序的公寓生活管理系统-程序员宅基地

文章浏览阅读223次。该系统将提供便捷的信息发布、物业报修、社区互动等功能,为小区居民提供更加便利、高效的服务。引言: 随着城市化进程的加速,小区管理成为一个日益重要的任务。因此,设计一个基于微信小程序的小区管理系统成为了一项具有挑战性和重要性的毕设课题。本文将介绍该小区管理系统的设计思路和功能,以期为小区提供更便捷、高效的管理手段。四、总结与展望: 通过本次毕设项目,我们实现了一个基于微信小程序的小区管理系统,为小区居民提供了更加便捷、高效的服务。通过该系统的设计与实现,能够提高小区管理水平,提供更好的居住环境和服务。_ssm基于微信小程序的公寓生活管理系统

如何正确的使用Ubuntu以及安装常用的渗透工具集.-程序员宅基地

文章浏览阅读635次。文章来源i春秋入坑Ubuntu半年多了记得一开始学的时候基本一星期重装三四次=-= 尴尬了 觉得自己差不多可以的时候 就吧Windows10干掉了 c盘装Ubuntu 专心学习. 这里主要来说一下使用Ubuntu的正确姿势Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的开源GNU/Linux操作系统,Ubuntu 是基于DebianGNU/Linux,支..._ubuntu安装攻击工具包

JNI参数传递引用_jni引用byte[]-程序员宅基地

文章浏览阅读335次。需求:C++中将BYTE型数组传递给Java中,考虑到内存释放问题,未采用通过返回值进行数据传递。public class demoClass{public native boolean getData(byte[] tempData);}JNIEXPORT jboolean JNICALL Java_com_core_getData(JNIEnv *env, jobject thisObj, jbyteArray tempData){ //resultsize为s..._jni引用byte[]

三维重建工具——pclpy教程之点云分割_pclpy.pcl.pointcloud.pointxyzi转为numpy-程序员宅基地

文章浏览阅读2.1k次,点赞5次,收藏30次。本教程代码开源:GitHub 欢迎star文章目录一、平面模型分割1. 代码2. 说明3. 运行二、圆柱模型分割1. 代码2. 说明3. 运行三、欧几里得聚类提取1. 代码2. 说明3. 运行四、区域生长分割1. 代码2. 说明3. 运行五、基于最小切割的分割1. 代码2. 说明3. 运行六、使用 ProgressiveMorphologicalFilter 分割地面1. 代码2. 说明3. 运行一、平面模型分割在本教程中,我们将学习如何对一组点进行简单的平面分割,即找到支持平面模型的点云中的所有._pclpy.pcl.pointcloud.pointxyzi转为numpy

以NFS启动方式构建arm-linux仿真运行环境-程序员宅基地

文章浏览阅读141次。一 其实在 skyeye 上移植 arm-linux 并非难事,网上也有不少资料, 只是大都遗漏细节, 以致细微之处卡壳,所以本文力求详实清析, 希望能对大家有点用处。本文旨在将 arm-linux 在 skyeye 上搭建起来,并在 arm-linux 上能成功 mount NFS 为目标, 最终我们能在 arm-linux 里运行我们自己的应用程序. 二 安装 Sky..._nfs启动 arm

攻防世界 Pwn 进阶 第二页_pwn snprintf-程序员宅基地

文章浏览阅读598次,点赞2次,收藏5次。00为了形成一个体系,想将前面学过的一些东西都拉来放在一起总结总结,方便学习,方便记忆。攻防世界 Pwn 新手攻防世界 Pwn 进阶 第一页01 4-ReeHY-main-100超详细的wp1超详细的wp203 format2栈迁移的两种作用之一:栈溢出太小,进行栈迁移从而能够写入更多shellcode,进行更多操作。栈迁移一篇搞定有个陌生的函数。C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 _pwn snprintf

推荐文章

热门文章

相关标签