以下内容摘自《步步惊芯——软核处理器内部设计分析》一书
1、一个简单的汇编程序
上一节安装好了GNU编译工具,还设置了虚拟机与宿主机的共享文件夹,下面我们就小试牛刀,写一个简单的程序,需要读者朋友们了解的是本书所有的测试代码都是很简单的汇编程序,因为即使最简单C语言代码(如:HelloWorld)经过编译后也会得到大量目标代码,而我们的目的是了解处理器内部的工作过程,所以大量的目标代码容易分散我们的精力,为此示例代码一律采用汇编,有的甚至只有几条指令,但也能说明问题。在Ubuntu中新建一个Document,文件名可以为Example.S,输入下面的代码,我们的第一个汇编程序。
.section .text,"ax" #定义了一个Section,Section名为.text,并且是可执行Section
.org 0x100 #OR1200处理器默认从地址0x100处开始执行,所以我们的代码从0x100开始
.global _start
_start:
l.andi r0,r0,0 #OR1200的r0寄存器应该始终为0,所以这里将其设置为0
l.extwz r1,r0 #下面两条指令是初始化寄存器r1、r2,使其都为0
l.extwz r2,r0
l.addi r1,r1,0x0A #r1的值加上0x0A存储到r1中,使得r1为0x0A
l.add r2,r2,r1 #r1的值加上r2的值存储到r2中,使得r2为0x0A
l.nop 0x0001 #空指令,但对模拟器有特殊含义
通过注释可知上述代码非常简单,只是几个简单的寄存器操作指令,现在不懂没有关系,只需要知道程序执行最后使得寄存器r1、r2都为0x0A,借助这么一个简单的程序,足够我们了解编译、链接、模拟器执行、仿真的全部步骤了。
2、编译及ELF文件介绍
在终端中首先使用cd命令将路径调整到上述Example.S所在目录,然后使用如下指令编译代码:
or32-elf-as Example.S –o Example.o
图2.11 Example.o的开始部分
遇到什么学什么,这是笔者的一贯宗旨,下面就简单介绍一下ELF文件,读者朋友中如果谁对这不感兴趣或者希望尽快了解编译链接过程的可以跳过下面的分析,直接阅读2.2.3节。
ELF(Executable and Linkable Format)可执行链接格式,是UNIX系统实验室(USL)作为应用程序二进制接口(ABI:Application Binary Interface)而开发和发布的。ELF目标文件有三种类型:
(1)可重定位(Relocatable)文件:保存着代码和适当的数据,用来和其他Object文件一起创建一个可执行文件或共享文件。
(2)可执行(Executable)文件:保存着一个用来执行的程序,该文件指出了如何来创建程序进程映象。
(3)共享目标文件:包含了在两种使用环境中链接的代码和数据。首先链接器(ld)可以将它和其余可重定位文件和共享目标文件一起处理,生成另外一个目标文件(比如:编译器和链接器把*.o和*.so一起装配成一个*.exe文件)。其次,动态链接器(Dynamic Linker)可将它与某个可执行文件以及其它共享目标文件组合在一起创建进程映像(比如:动态加载器把.exe程序和*.so加载进内存执行)。
无论何种类型的ELF文件,其结构都是相同的。ELF文件由四部分组成:ELF header、Program header table、Sections、Section header table。其最开始的部分就是ELF header,定义如下:#define EI_NIDENT 16
typedef struct{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;