文章和代码已归档至【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个文件,如下图所示:

其中一个初始化汇编语言文件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_HandlerSWI_Handler        b SWI_HandlerPrefetch_handler   b Prefetch_handlerAbort_Handler      b Abort_Handler                   nop   ;Reserved vectorIRQ_Handler        b IRQ_HandlerFIQ_Handler        b FIQ_HandlerReset_Handler     ;Reset中断,为整个中断的理论入口点                     bl initstack    ;初始化各模式下的堆栈指针                                          ;切换至用户模式堆                 msr cpsr_c,#0xd0    ;110  10000                              bl Mainhalt  b haltinitstack    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+128stacksvc     dcd  svcstackspace+128stackirq     dcd  irqstackspace+128stackfiq     dcd  fiqstackspace+128stackabt     dcd  abtstackspace+128stackund     dcd  undstackspace+128  area Interrupt,data,READWRITE  ;调配堆栈空间usrstackspace space 128svcstackspace space 128irqstackspace space 128fiqstackspace space 128abtstackspace space 128undstackspace 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.如何建设异样矢量入口表?

答:建设异样矢量入口表须要设置中断类型号,并且要设置中断服务子程序段地址,以依据异样矢量表进入不同模式的中断程序。在试验程序中也有定义:

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

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

3.如何在C语言中调用汇编语言函数,并实现参数传递?

答:为了保障程序调用时参数的正确传递,汇编程序设计要恪守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的变动状况,并解释其中的起因。

批改程序如下:

答:由上可知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解读,我的项目源码,面经总结。