文章和代码已归档至【Github库房:hardware-tutorial】,需求的朋友们自取。或者重视大众号【AIShareLab】,回复 嵌入式 也可获取。

一、试验意图

(1) 把握树立根本完整的ARM 工程,包含发动代码,C言语程序等;

(2) 了解ARM发动进程,学会编写简略的C 言语程序和汇编发动代码并进行调试;

(3) 把握怎么指定代码进口地址与进口点;

(4) 把握经过memory/register/watch/variable 窗口分析判断成果。

二、试验环境

硬件:PC机。

软件:ADS1.2 集成开发环境

三、试验内容

运用汇编言语编写初始化程序,并引导至C言语main函数,用汇编言语编写延时函数完结毫秒级的延时,在C言语中调用延时函数,完结1s钟定时。

四、试验要求

(1) 在ADS下创立一个工程armasmc,编写3个文件,如下图所示:

嵌入式ARM设计编程(四) ARM启动过程控制

其间一个初始化汇编言语文件Init.s,该文件中主要完结反常矢量表的树立,形式仓库初始化,并将程序引导至C言语的main函数。

C言语程序保存为armasmc.c。 C言语中调用汇编言语文件delay.s中的毫秒延时程序delayxms,C言语将延时的毫秒数经过参数传递到汇编言语,汇编言语完结延时,然后回来C言语函数。

经过AXD运用单步履行办法调试程序。调查程序履行进程中的寄存器及存储器的改变状况。

(2)试验进程中请记录并思考以下内容:

1)怎么树立反常矢量进口表?

2)怎么在汇编言语中切换至C言语的main函数?。

3)怎么在C言语中调用汇编言语函数,并完结参数传递?

4)汇编言语函数中用到的寄存器怎么维护与康复,为什么要维护参阅程序中的R11?

5)将delay.s中的R11改成R4,并将两条R11 的维护与康复句子stmfd sp!,{r11} 和ldmfd sp!,{r11}删掉,在C言语程序中的句子i–处设置端点,调查运转进程中变量i的改变状况,并解说其间的原因。

五、试验状况:

1、试验源代码(含注释):

Init.s代码:

;************************ entry.s ****************************
 IMPORT Main  ;在汇编程序调用该c程序前要在汇编言语程序中运用IMPORT伪操作来声明该c程序
  area Init,code,readonly   ;界说CODE片段Init 只读 
  entry     ;设置程序进口伪指令
  code32   ;以下为32位的ARM程序
; *********** Setup interrupt/exception vector *******************
start              b Reset_Handler        ;反常矢量表,依据反常矢量表进入不同形式的间断程序      
Undefined_Handler  b Undefined_Handler
SWI_Handler        b SWI_Handler
Prefetch_handler   b Prefetch_handler
Abort_Handler      b Abort_Handler
                   nop   ;Reserved vector
IRQ_Handler        b IRQ_Handler
FIQ_Handler        b FIQ_Handler
Reset_Handler     ;Reset间断,为整个间断的实践进口点        
             bl initstack    ;初始化各形式下的仓库指针
             ;切换至用户形式堆    
             msr cpsr_c,#0xd0    ;110  10000
             bl Main
halt  b halt
initstack    mov r0,lr   ;r0<--lr,由于各种形式下r0是相同的而各个形式?                            
             ;设置管理形式仓库
             msr cpsr_c,#0xd3    ;110  10011  
             ldr sp,stacksvc
             ;设置间断形式仓库
             msr cpsr_c,#0xd2    ;110  10010
             ldr sp,stackirq  
             ;设置快速间断形式仓库
             msr cpsr_c,#0xd1    ;110  10001
             ldr sp,stackfiq
             ;设置间断形式仓库      
             msr cpsr_c,#0xd7    ;110  10111
             ldr sp,stackabt
            ;设置未界说形式仓库   
             msr cpsr_c,#0xdb    ;110  11011
             ldr sp,stackund
             ;设置系统形式仓库    
             msr cpsr_c,#0xdf    ;110  11111
             ldr sp,stackusr
             mov pc,r0 ;回来
  LTORG      
stackusr     dcd  usrstackspace+128
stacksvc     dcd  svcstackspace+128
stackirq     dcd  irqstackspace+128
stackfiq     dcd  fiqstackspace+128
stackabt     dcd  abtstackspace+128
stackund     dcd  undstackspace+128
  area Interrupt,data,READWRITE  ;分配仓库空间
usrstackspace space 128
svcstackspace space 128
irqstackspace space 128
fiqstackspace space 128
abtstackspace space 128
undstackspace space 128
       end

delay.s代码:

;************************* delay.s *****************************
  EXPORT delayxms ;EXPORT伪指令用于在程序中声明一个大局的标号,该标号可在其他的文件中引用
  area delay,code,readonly  ;界说code片段delay只读
  code32  ;以下为32位的ARM程序
;下面是延时若干ms的子程序      
delayxms
     stmfd sp!,{r11} ; 寄存器入栈
     sub r0,r0,#1 ;r0=r0-1
     ldr r11,=1000 ;加载至r11中
loop2
     sub r11,r11,#1 ;每次将r11自减一
     cmp r11,#0x0 ;将r11与0比较
     bne loop2  ;比较的成果不为0,则持续调用loop2  
     cmp r0,#0x0    ;将r0与0比较
     bne delayxms   ;比较的成果不为0,则持续调用delayxms
     ldmfd sp!,{r11};
     mov pc,lr;回来
     end

armasmc.c代码:

//*************************armasmc.c******************************
#include <stdio.h>
int Main()
{  
  extern void delayxms(int xms);  //在C程序调用汇编程序之前需求在C言语程序中运用extern关键词来声明该汇编程序
  int i=100;
  while(1)
  {
     delayxms(1000); // 调用delayxms汇编程序
     i--;
     if(i==0)
       i=100;
  }
  return 0;
}

2、试验进程(含成果截图及相应文字解说):

1.怎么树立反常矢量进口表?

答:树立反常矢量进口表需求设置间断类类型,而且要设置间断服务子程序段地址,以依据反常矢量表进入不同形式的间断程序。在试验程序中也有界说:

嵌入式ARM设计编程(四) ARM启动过程控制

2.怎么在汇编言语中切换至C言语的main函数?

嵌入式ARM设计编程(四) ARM启动过程控制

答:由上代码可知,为确保程序调用时参数的正确传递,汇编程序设计要恪守ATPCS(ARM-Thumb Produce Call Standard),它是ARM程序和Thumb程序中子程序调用的根本规矩,意图是为了使独自编译的C言语程序和汇编程序之间能够彼此调用。这些根本规矩包含子程序调用进程中寄存器的运用规矩、数据栈的运用规矩和参数的传递规矩。在C程序中不需求任何关键字来声明将被汇编言语调用的C程序,但需求在汇编言语程序之前运用IMPORT伪操作来声明该C程序。在汇编程序中经过BL指令来调用子程序。同时,汇编程序能够经过地址直接拜访在C言语程序中声明的大局变量。经过运用IMPORT关键词引入大局变量,并运用LDR和STR指令依据大局变量的地址能够拜访它们。

3.怎么在C言语中调用汇编言语函数,并完结参数传递?

嵌入式ARM设计编程(四) ARM启动过程控制

嵌入式ARM设计编程(四) ARM启动过程控制

答:为了确保程序调用时参数的正确传递,汇编程序设计要恪守ATPCS。在汇编程序中需求运用EXPORT伪操作来声明,同时,在C程序中调用该汇编程序之前需求在C言语程序中运用extern关键词来声明该汇编程序。

4.汇编言语函数中用到的寄存器怎么维护与康复,为什么要维护参阅程序中的R11?

答:汇编言语函数中用到的寄存器经过压栈来维护,出栈来康复。依据ATPCS规矩,R11对应ARM 状况局部变量寄存器8,R11中含有循环次数的重要参量,因此要维护R11防止在程序运转与调用进程中受到影响而导致程序反常。

5.将delay.s中的R11改成R4,并将两条R11 的维护与康复句子stmfd sp!,{r11} 和ldmfd sp!,{r11}删掉,在C言语程序中的句子i–处设置端点,调查运转进程中变量i的改变状况,并解说其间的原因。

修正程序如下:

嵌入式ARM设计编程(四) ARM启动过程控制

答:由上可知R4对应局部变量寄存器1,即变量i,因此在子程序delay.s中,R4的值减为0,若不进行维护,则回来C程序后自减-1,导致变量i的值变为-1,此刻将无法满意0的条件,也就无法履行if,导致i会一直递减下去,最终无法中止。

六、总结

本次有关汇编与C言语彼此调用的部分,树立反常矢量进口表的办法,即需求设置间断类类型,而且要设置间断服务子程序段地址,以依据反常矢量表进入不同形式的间断程序。此外,还有ARM程序和Thumb程序中子程序调用的根本规矩ATPCS(ARM-Thumb Produce Call Standard),意图是为了使独自编译的C言语程序和汇编程序之间能够彼此调用。这些根本规矩包含子程序调用进程中寄存器的运用规矩、数据栈的运用规矩和参数的传递规矩,为调用提供了相关的规范。其间汇编程序拜访大局C变量的办法是:汇编程序能够经过地址直接拜访在C言语程序中声明的大局变量。经过运用IMPORT关键词引入大局变量,并运用LDR和STR指令依据大局变量的地址能够拜访它们。在C言语程序中调用汇编程序的办法是:在汇编程序中需求运用EXPORT伪操作来声明,使得本程序能够被其它程序调用。同时,在C程序调用该汇编程序之前需求在C言语程序中运用extern关键词来声明该汇编程序。而在汇编程序中调用C言语程序的办法是:在C程序中不需求运用任何关键字来声明将被汇编言语调用的C程序,但是在汇编程序调用该C程序之前需求在汇编言语程序中运用IMPORT伪操作来声明该C程序。在汇编程序中经过BL指令来调用子程序。


欢迎重视大众号【AIShareLab】,一起交流更多相关知识,前沿算法,Paper解读,项目源码,面经总结。