2012-05-24 53 views
4

用汇编写入可以减少代码大小和执行时间。但是,假如我有足够的记忆和足够的时间。我可以只使用C代码并引导设备吗?我的意思是,从开机直接运行C代码。我特别感兴趣的是ARM处理器。为什么所有的ARM bootloader都有汇编代码?

+0

我不知道你在问什么。 – leppie

回答

1

我也不知道确切的答案。我只是提出一些我能想到的(减去内存和效率)的原因:
- 该代码是非常具体的设备,无需进行编译和其他地方运行
- 使用特殊指令
(?) - 启动加载程序运行时的状态与正常程序(?)(堆栈,堆)不同

声明:此答案可能包含错误信息。这里不要重视任何事情。

1

引导加载程序负责在设备启动时对其进行初始化。在这一点上,汇编器没有别的可用。汇编器部分通常保持尽可能小,并负责初始化系统,以便操作系统的一部分和例如最小的C运行时间可以加载到内存中并执行,并且在此之后其他初始化任务可以使用例如C.

有些链接可能会有所帮助:

Wikipedia bootloader entry

U-boot design principles

希望这是有帮助的。

6

其实你可以为ARM的Cortex-M3 microcontrollers做一个C-only固件。因为它的向量表包含栈指针的条目,所以它的值将被处理器初始化,并且您可以使用直接从重置开始的编译代码。您仍然需要设置外设并初始化C库环境,但不必在汇编器中完成。 Cortex-M3的同时自动保存在中断处理程序入口易失性寄存器,使他们也可以直接在C.

也就是说,大多数编译器厂商仍然提供用汇编语言编写的启动,因为它提供了最大程度的控制写入。

+1

我想添加(只是为了清楚),矢量表可以是C数组,也可以是Cortex-M3。只是使用...'__attribute __((section(“。isr_vector”)))VectorFunc g_pfnVectors [] = {...};' – 2013-05-05 00:13:43

4

如前所述,Cortex-M3的是特殊的,会允许这样的事情,还好有一个例外,你仍然需要一些ASM或其他一些魔法打造量表调用C代码。

一般是没有,需要回答一些组件。处理器是通用的,他们通常不知道你为程序和数据以及堆栈设置了什么地址空间,寄存器,特别是堆栈指针,通常被初始化为一些已知的值,例如零。处理器一般都知道有一个启动序列,要么是有一个地址开始执行,要么是一个地址,在这个地址找到一个开始执行的地址。该地址表,一个用于复位,一个用于中断等,由引导代码的程序员放置在那里,虽然可以用C来管理,不值得花费精力,但更容易编写几行asm来构建该向量表。 (这是皮层-m的情况)

所以至少你需要设置一个堆栈指针,然后分支到条目C代码,从那里你可以逃脱运行C.现在,如果这是一个arm并不是cortex-m,那么你有多个堆栈来设置(如果你想使用中断,处理故障等),你必须使用特定的asm指令来执行该设置,所以需要asm,real或inline 。

如果您习惯使用.data或期望.bss为零,则必须执行此操作,但某些代码必须将bss清零并准备.data。通常你的系统(即使是你的台式机/笔记本电脑)将从闪存启动,如果你有.data,.data需要在闪存中,但希望被读/写,所以你需要将这些数据从闪存复制到它的家园在内陆,好吧,你需要先运行并运行(见下文)来做到这一点。

不是在过去的美好时光,但肯定今天与德拉姆你无法打开并开始使用内存,有很多代码需要dram和运行。是的,这段代码是用C语言编写的,可能不是asm(尽管出于性能方面的原因,asm可能被用来利用特定的指令,而不一定会让C编译器为你生成)。

所以你有一个不同的场景一般,不一定具体到手臂。我将列出一些但不是每个细微差别

1)你有一个系统使用sram或内部ram,不需要初始化,你没有使用.data,你的代码不会假定.bss已被清零。通常情况下,最小化是初始化堆栈指针并分支到C入口点(main,或任何你称之为的)。

2)你有一个系统使用sram或内部ram,不需要初始化,你正在使用.data,你希望在你的C代码开始之前就存在(对于C程序员来说很典型)和.bss在你的C代码开始之前为零(也是典型的,但幸好gcc开始抱怨这样做的代码)。由于您的C代码在这种情况下期望在C代码运行之前准备好这些东西,因此将.bss归零并将.data从闪存复制到RAM会发生在asm中。这是你最常见的场景,请查看许多针对不同处理器的crt0.s例程,这是常用主题,设置堆栈指针,零bss,将.data分支复制到main。 3)你有一个系统有一些内部的sram,不需要初始化,但你期望使用的主存是dram。这是两个步骤,您的第一个引导加载程序仍然需要设置堆栈指针,根据您的首选项可选地设置零.bss和复制.data,然后分支到第一个引导加载程序的入口点。这个引导程序将启动dram系统。现在,该引导加载程序可以选择复制.data和零.bss(现在可以在C中),然后转到主引导加载程序入口点/函数,该入口函数需要并使用较大的主内存。

4)你有一个微处理器的x86处理器,你需要在启动时修补微代码,我没有这方面的个人知识,但会假设你应该使用的指令数量有限,因为你正在改变微编码的一些,或者你复制到一些内存然后翻转一下,它奇迹般地切换补丁,你执行变化,不知道,但我敢打赌,一些组装是必需的。

请记住,许多C库调用都在组装中。所以C是组装的,尤其是手臂。你避免所有的分歧,乘法,模数,浮点数等吗?你从不使用任何字符串函数或复制函数吗?你是否使用C库函数?这很可能是你正在使用的asm,并且不知道它。 memcpy通常是手动调整的,尤其是手臂。如果你在代码中使用结构,编译器可能会抛出memcpys,具体取决于你使用的是什么以及如何使用它们。分而定模。繁殖有时。浮点,通常是asm,即使有fpu也是如此。你确实没有写过这个asm,但是有可能是asm,并且你的引导程序不会没有asm(如果你使用这些库)存在。

你的标题问题,暗示只有一个引导程序的程序集是错误的,引导程序大多不是程序集。几乎总是需要一些组件。

cortex-m是一个独特的野兽,因为它的设计使您不必使用特殊指令或asm来包装中断(或让编译器为您做这件事)。不典型。虽然cortex-m有一个巨大的向量表。好奇你如何用C编写这个表。我有一些想法如何做,但是它对于asm来说更容易,即使asm实际上并不是汇编程序的指令(.word this_handler,.word that_handler) 。至少在传统ARM的32位ARM7指令ARM内核中,您必须设置堆栈并在asm中至少分支到C代码,除非您玩编译器游戏,异常处理程序还需要一点asm,只是几行。我不得不怀疑这个问题的根源。引导加载程序与处理器和附属设备非常紧密地联系在一起,编写引导加载程序的程序员必须能够很方便地使用硬件寄存器等,这意味着对于该处理器的指令集有一定的舒适度。避免引导程序中的所有asm是一个问题。即使使用cortex-m只是因为你可以直接从向量表转换为C代码,你仍然需要验证你使用的编译器符合硬件调用约定,而不仅仅是一些通用的arm调用约定,以确保保留一定范围的寄存器并在返回时使用正确的指令,这意味着对编译器生成的代码进行反汇编和手动/可视化检查,但是在这个级别上,尽管只是阅读,与写入asm相当。

+0

http://github.com/dwelch67我有很多没有操作的嵌入式arm示例系统或引导加载程序,实质上它们是它们自己的引导加载程序,尽管我没有为cortex-m做这个技巧,您可以看到引导加载程序有多简单,需要多少asm。零汇率绝对不是我的目标,所以我没有达到这个极限。 –