堆栈指针,如何使用引导启动程序Bootloader?

2024-07-15 02:53:41 85阅读

堆栈指针,如何使用引导启动程序Bootloader?

一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader), Linux 内核,文件系统,应用程序。 当系统首次引导时,或系统被重置时,处理器会执行一个位于Flash/ROM中的已知位置处的代码,Bootloader就是这第一段代码。它主要用来初始化处理器及外设,然后调用 Linux 内核。Linux 内核在完成系统的初始化之后需要挂载某个文件系统作为根文件系统(Root Filesystem),然后加载必要的内核模块,启动应用程序。这就是嵌入式Linux系统启动过程 Linux 引导的整个过程。 根文件系统是 Linux 系统的核心组成部分,它可以作为Linux 系统中文件和数据的存储区域,通常它还包括系统配置文件和运行应用软件所需要的库。应用程序可以说是嵌入式系统的“灵魂”,它所实现的功能通常就是设计该嵌入式系统所要达到的目标。如果没有应用程序的支持,任何硬件上设计精良的嵌入式系统都没有实用意义。 从以上分析可以看出 Bootloader在运行过程中虽然具有初始化系统和执行用户输入的命令等作用,但它最根本的功能就是为了启动 Linux 内核,让我们进一步分析 Bootloader 和 Linux 内核在嵌入式系统中的关系和作用。 Bootloader

1、Bootloader基本概述 Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于 PC 机上的 BIOS。Bootloader是依赖于硬件而实现的,特别是在嵌入式领域,为嵌入式系统建立一个通用的Bootloader是很困难的,但为了能达到启动Linux 内核的目的,所有的 Bootloader都必须具备以下功能: 1) 初始化 RAM 因为 Linux 内核一般都会在 RAM 中运行,所以在调用 Linux 内核之前 Bootloader 必须设置和初始化 RAM,为调用 Linux内核做好准备。初始化 RAM 的任务包括设置 CPU 的控制寄存器参数,以便能正常使用 RAM 以及检测RAM 大小等。 2) 初始化串口端口 在 Linux 的启动过程中有着非常重要的作用,它是 Linux内核和用户交互的方式之一。Linux 在启动过程中可以将信息通过串口输出,这样便可清楚的了解 Linux 的启动过程。虽然它并不是 Bootloader 必须要完成的工作,但是通过串口输出信息是调试 Bootloader 和Linux 内核的强有力的工具,所以一般的 Bootloader 都会在执行过程中初始化一个串口作为调试端口。 3) 检测处理器类型 Bootloader在调用 Linux内核前必须检测系统的处理器类型,并将其保存到某个常量中提供给 Linux 内核。Linux 内核在启动过程中会根据该处理器类型调用相应的初始化程序。 4) 设置 Linux启动参数 Bootloader在执行过程中必须设置和初始化 Linux 的内核启动参数。 5) 调用 Linux内核映像 Bootloader完成的最后一项工作便是调用 Linux内核。如果 Linux 内核存放在 Flash 中,并且可直接在上面运行(这里的 Flash 指 Nor Flash),那么可直接跳转到内核中去执行。但由于在 Flash 中执行代码会有种种限制,而且速度也远不及 RAM 快,所以一般的嵌入式系统都是将 Linux内核拷贝到 RAM 中,然后跳转到 RAM 中去执行。

堆栈指针,如何使用引导启动程序Bootloader?

2、Bootloader启动过程 嵌入式Linux系统通过Bootloader引导,一上电,就要执行Bootloader来初始化系统。在完成对系统的初始化任务之后,它会将非易失性存储器(通常是 Flash或 DOC 等)中的Linux 内核拷贝到 RAM 中去,然后跳转到内核的第一条指令处继续执行,从而启动 Linux 内核。Bootloader 和 Linux 内核有着密不可分的联系。 Bootloader多数有两个阶段的启动过程: Stage1: 基本的硬件初始化 为加载stage2准备RAM空间 拷贝内核映像和文件系统映像到RAM中 设置堆栈指针sp 跳到stage2的入口点 Stage2: 初始化本阶段要使用到的硬件设备 检测系统的内存映射 加载内核映像和文件系统映像 设置内核的启动参数 嵌入式系统中广泛采用的非易失性存储器通常是 Flash,而 Bootloader就位于该存储器的最前端,所以系统上电或复位后执行的第一段程序便是 Bootloader。Bootloader在flash中的存储示意图如下: Bootloader启动流程图

3、Bootloader 的启动方式 3.1网络启动方式 这种方式的开发板不需要较大的存储介质,跟无盘工作站有点类似,但是使用这种启动方式之前,需要把Bootloader安装到板上的EPROM或者Flash中。Bootloader通过以太网接口远程怎么玩Linux内核映像或者文件系统。Bootloader怎么玩文件一般都使用TFTP网络协议,还可以通过DHCP的方式动态配置IP地址。 3.2硬盘启动方式 传统的Linux系统运行在台式机或者服务器上,这些计算机一般都使用BIOS引导,并使用磁盘作为存储介质。Linux传统上是LILO (Linux Loader) 引导,后来又出现了GUN的软件 (Grand Unified Bootloader) 。 这两种Bootloader广泛应用在X86的Linux系统上。 3.3 Flash启动方式 大多数嵌入式系统上都使用Flash存储介质。Flash有很多类型,包括NOR Flash、NAND Flash和其它半导体盘。它们之间的不同在于: NOR Flash 支持芯片内执行(XIP, eXecute In Place),这样代码可以在Flash上直接执行而不必拷贝到RAM中去执行。而NAND Flash并不支持XIP,所以要想执行 NAND Flash 上的代码,必须先将其拷贝到 RAM中去,然后跳到 RAM 中去执行。NOR Flash 使用最为普遍。Bootloader一般放在Flash的底端或者顶端,这需要根据处理器的复位向量来进行设置。可以配置成MTD设备来访问Flash分区

三菱plc堆栈的用途?

用于建模型

1. 堆栈指令是FX系列中新增的基本指令,用于多重输出电路,为编程带来便利、在FX系列PLC中有11个存储单元,它们专门用来存储程序运算的中间结果,被称为栈存储器。

堆栈是计算机中一种先进后出的数据结构,由栈区和栈顶指针组成。

堆栈有两种操作,压栈(进栈)和弹栈(出栈),他们均只能在栈顶进行。

什么是电脑USP?

USP:UnitedStatesPatent美国专利USP:UnitedStatesPharmacopoeia美国药典USP:UserStackPointer用户堆栈指针USP:UniversalSelbstladePistol通用自动装填手枪USP:UniqueSellingProposition独特销售主张USP:UniversityoftheSouthPacific南太平洋大学USP:UniversityofSãoPaulo圣保罗大学USP:UniversityoftheSciencesinPhiladelphia费城理科大学不知道你的电脑主机上的USP代表的是何种意思。

pic16单片机堆栈到底在rom还是ram中?

RAM中,建议找本教材看看, RAM中,默认为07H,就是R7。为了避免堆栈中数据和R7中数据冲突,一般在程序开始时,把堆栈指针设在RAM的后端

80x86调用函数指令是什么?

CALL - 调用过程 操作码 指令 说明 E8 cw CALL rel16 相对近调用,位移量相对于下一条指令 E8 cd CALL rel32 相对近调用,位移量相对于下一条指令 FF /2 CALL r/m16 绝对间接近调用,地址由 r/m16 给出 FF /2 CALL r/m32 绝对间接近调用,地址由 r/m32 给出 9A cd CALL ptr16:16 绝对远调用,地址由操作数给出 9A cp CALL ptr16:32 绝对远调用,地址由操作数给出 FF /3 CALL m16:16 绝对间接远调用,地址由 m16:16 给出 FF /3 CALL m16:32 绝对间接远调用,地址由 m16:32 给出 说明 将过程链接信息保存到堆栈上,并分支到目标(调用目标)操作数指定的过程(被调用过程)。

目标操作数指定被调用过程中第一条指令的地址。此操作数可以是立即数、通用寄存器或内存位置。此指令可用于执行四种不同类型的调用: 近调用 - 调用当前代码段(CS 寄存器当前指向的段)中的过程,有时称为段内调用。远调用 - 调用当前代码段之外的段中的过程,有时称为段间调用。特权级别间远调用 - 对特权级别与当前执行程序或过程不同的段中的过程进行的远调用。任务切换 - 调用不同任务中的过程。后两种调用类型(特权级别间调用与任务切换)只能在保护模式中执行。如需有关近调用、远调用及特权级别间调用的详细信息,请参阅“IA-32 英特尔(R) 体系结构软件开发人员手册”第 1 卷第 6 章中标题为“使用 Call 与 RET 调用过程”的部分。如需有关使用 CALL 指令执行任务切换的详细信息,请参阅“IA-32 英特尔(R) 体系结构软件开发人员手册”第 3 卷第 6 章“任务管理”。近调用。执行近调用时,处理器将 EIP 寄存器的值(包含 CALL 指令后面的指令的偏移量)压入堆栈(稍后用作返回指令指针)。然后,处理器分支到当前代码段中由目标操作数指定的地址。目标操作数指定代码段中的绝对偏移量(即相对于代码段基址的偏移量)或相对偏移量(相对于 EIP 寄存器中指令指针的当前值的有符号位移量,此指针指向 CALL 指令后面的指令)。执行近调用时,CS 寄存器保持不变。对于近调用,绝对偏移量在通用寄存器或内存位置(r/m16 或 r/m32)中间接指定。操作数大小属性确定目标操作数的大小(16 位或 32 位)。绝对偏移量直接加载到 EIP 寄存器。如果操作数大小属性是 16,则 EIP 寄存器的两个高位字节清除为零,得到大小最大为 16 位的指令指针。(使用堆栈指针 [ESP] 作为基址寄存器来间接访问绝对偏移量时,使用的基址值是 ESP 在指令执行之前的值)。在汇编代码中,相对偏移量(rel16 或 rel32)通常指定为标签,但是在机器代码级别,它的编码形式是有符号的 16 位或 32 位立即数。此值会加到 EIP 寄存器中的值上。对于绝对偏移量,操作数大小属性确定目标操作数的大小(16 位或 32 位)。实地址模式或虚 8086 模式中的远调用。在实地址模式或虚 8086 模式中执行远调用时,处理器将 CS 与 EIP 寄存器的当前值压入堆栈,作为返回指令指针使用。然后,处理器执行指向目标操作数指定的代码段与偏移量的“远分支”操作,以便调用被调用过程。这里,绝对远地址由目标操作数使用指针(ptr16:16 或 ptr16:32)直接指定,或是使用内存位置(m16:16 或 m16:32)间接指定。使用指针方法时,被调用过程的段与偏移量在指令中编码,编码时使用 4 字节(16 位操作数大小)或 6 字节(32 位操作数大小)远地址立即数。使用间接方法时,目标操作数指定内存位置,它包含 4 字节(16 位操作数大小)或 6 字节(32 位操作数大小)远地址。操作数大小属性确定远地址中偏移量的大小(16 位或 32 位)。远地址直接加载到 CS 与 EIP 寄存器。如果操作数大小属性为 16,则 EIP 寄存器的两个高位字节清除为零。保护模式中的远调用。处理器在保护模式中操作时,CALL 指令可用于执行以下三种类型的远调用: 相同特权级别远调用。不同特权级别远调用(特权级别间调用)。任务切换(远调用另一项任务)。在保护模式中,处理器总是使用远地址中的段选择器部分访问 GDT 或 LDT 中相应的描述符。描述符类型(代码段、调用门、任务门或 TSS)与访问权限确定要执行的调用操作类型。如果所选描述符是代码段的,则执行相同特权级别代码段远调用。(如果选择的代码段在另一个特权级别中,并且代码段为非相容代码段,则生成一般保护性异常)。在保护模式中执行的相同特权级别远调用与在实地址模式或虚 8086 模式中执行的远调用非常相似。绝对远地址由目标操作数使用指针(ptr16:16 或 ptr16:32)直接指定,或是使用内存位置(m16:16 或 m16:32)间接指定。操作数大小属性确定远地址中偏移量的大小(16 位或 32 位)。新的代码段选择器及其描述符加载到 CS 寄存器,相对于指令的偏移量加载到 EIP 寄存器。请注意,调用门(在下一段叙述)也可用于执行相同特权级别上代码段的远调用。此机制提供了另一层面的间接调用,进行 16 位与 32 位代码段之间的调用时,首选这种方法。执行特权级别间远调用时,被调用过程的代码段必须通过调用门访问。目标操作数指定的段选择器确定调用门。同样地,在这里,目标操作数可以使用指针(ptr16:16 或 ptr16:32)直接指定调用门的段选择器,或是使用内存位置(m16:16 或 m16:32)间接进行指定。处理器从调用门描述符中获取新代码段的段选择器与新的指令指针(偏移量)。(使用调用门时,忽略目标操作数的偏移量)。执行特权级别间调用时,处理器会切换到被调用过程的特权级别的堆栈。新堆栈段的段选择器在当前运行的任务的 TSS 中指定。执行堆栈切换之后,分支到新的代码段。(请注意,使用调用门对相同特权级别的段执行远调用时,不会发生堆栈切换)。在新堆栈中,处理器会压入以下值:调用过程堆栈的段选择器与堆栈指针、调用过程堆栈的一组参数(可选),以及调用过程代码段的段选择器与指令指针。(调用门描述符的值确定要将多少个参数复制到新的堆栈)。最后,处理器分支到新代码段中被调用过程的地址。使用 CALL 指令执行任务切换与通过调用门执行调用存在一定程度的相似。这里,目标操作数指定要切换到的任务的任务门段选择器(忽略目标操作数中的偏移量)。任务门则指向任务的 TSS,它包含任务代码与堆栈段的段选择器。TSS 还包含挂起任务之前要执行的下一条指令的 EIP 值。此指令指针值加载到 EIP 寄存器,以便任务从这个下一条指令再次执行。CALL 指令也可直接指定 TSS 的段选择器,这样就不用间接通过任务门。如需有关任务切换机制的详细信息,请参阅“IA-32 英特尔® 体系结构软件开发人员手册”第 3 卷第 6 章“任务管理”。请注意,使用 CALL 指令执行任务切换时,会将 EFLAGS 寄存器中的嵌套任务标志 (NT) 设置为 1,并且会同时加载新 TSS 的前一个任务链接字段与旧任务的 TSS 选择器。可以预见,代码会通过执行 IRET 指令暂停此嵌套任务,由于 NT 标志已设置为 1,此指令将自动使用前一个任务链接返回到调用任务。(如需有关嵌套任务的详细信息,请参阅“IA-32 英特尔® 体系结构软件开发人员手册”第 3 卷第 6 章“任务链接”)。使用 CALL 指令切换任务与 JMP 指令在这一点上是不同的,JMP 指令不会将 NT 标志设置为 1,因此 IRET 指令应该不会暂停任务。16 位与 32 位混合调用。在 16 位与 32 位代码段之间执行远调用时,应该通过调用门进行。如果是从 32 位代码段到 16 位代码段的远调用,则应该从 32 位代码段的头 64 KB 执行调用。这是因为指令的操作数大小属性设置为 16,所以只能保存 16 位返回地址偏移量。另外,应该使用 16 位调用门执行调用,以便将 16 位值压入堆栈。如需有关在 16 位与 32 位代码段之间执行调用的详细信息,请参阅“IA-32 英特尔(R) 体系结构软件开发人员手册”第 3 卷第 16 章“16 位与 32 位混合代码”。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。