ARM实验5_嵌入式C与汇编混合编程

更新时间:2023-05-31 01:09:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

昆明理工大学信息工程与自动化学院学生实验报告

( 2011 —2012 学年 第 1 学期 )

课程名称:ARM嵌入式系统结构 开课实验室:信自楼443 2012 年12月27日

一、实验目的

掌握建立基本完整的ARM工程,包含启动代码,连接脚本等; 阅读Embest S3CEV40启动代码,观察处理器启动过程;

学会使用Embest IDE 辅助信息窗口来分析判断调试过程和结果;

学会在Embest IDE环境中编写、编译与调试汇编和C语言相互调用的程序。 掌握通过memory/register/watch/variable窗口分析判断结果。 二、实验原理

1. ARM异常向量表

当正常的程序执行流程挂起时,称之为异常。在处理异常之前,必须保存当前的处理器状态,以便从异常程序返回时可以继续执行当前的程序。ARM异常向量表如表2-2所示。

由上可见,复位(Reset)入口是整个程序的实际入口点。因此,编写代码时,第一条语句在0x00000000处开始执行。

2. ARM过程调用ATPCS(ARM)

ATPCS是一系列用于规定应用程序之间相互调用的基本规则。 程序只要遵守ATPCS相应规则,就可以使用不同的源代码来编写程序。程序间的相互调用最主要的是解决参数传递问题。应用程序之间使用中间寄存器及数据栈来传递参数,其中第1~4个参数使用R0~R3,多于4个参数的则使用数据栈进行传递。

用不同语言编写的应用程序在调用时可以自定义参数传递的约定。使用具有一定意义的形式来传递,可以很好地解决参数个数问题。常用方法是把第1个或最后1个参数(包括个数本身)传递给应用程序。

ATPCS中寄存器的对应关系如表2-3所列。

表2-3 ATPCS规则中寄存器列表

3. 链接脚本文件

所有的链接都是通过链接脚本来控制实现的。这些链接脚本文件使用链接命令语言编写。

链接脚本的最主要作用是描述我们编写的文件中这么多个部分应该如何的相应摆放在输出文件中,并控制存储区如何定位这些输出文件。同时,如果需要,我们还可以使用链接脚本文件实现其它功能。

大部分链接脚本文件都是很简单的。最简单的链接脚本只有一行命令: SECTIONS。使用SECTIONS命令来告诉存储区应该如何摆放输出文件。

4.Embest IDE开发调试辅助窗口

使用Embest IDE嵌入式开发环境,用户可以使用源代码编辑窗口编写源文件程序。使用反汇编窗口观察程序代码的执行,使用Register窗口观察程序操作及CPU状态,使用外围寄存器窗口观察当前处理器的设置,使用Memory窗口观察内存单元使用情况,使用Watch或Variables窗口观察程序变量,使用操作控制台执行特殊命令。加上调试状态下丰富的右键快捷菜单功能,用户可以使用IDE实现或发现任何一部分应用软件,修改任何一个开发或运行时的错误。 三、实验内容

1. 使用汇编完成一个随机数产生函数,通过C语言调用该函数,产生一系列随机数,存放到数组里面。

2. 下面是ARM的启动文件init.s及链接脚本文件ldscript的参考程序: 参考程序init.s: #.arm

.global _start .text _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 IRQ_Handler: B IRQ_Handler FIQ_Handler: B FIQ_Handler Reset_Handler: LDR sp, =0x00002000

#---------------------------------------------------------------- #- Branch on C code Main function (with interworking)

#- Branch must be performed by an interworking call as either an ARM or Thumb #- main C function must be supported. This makes the code not position- #- independant. A Branch with link would generate errors

#---------------------------------------------------------------- .extern __main

ldr r0, = __main mov lr, pc bx r0

#---------------------------------------------------------------- #- Loop for ever

#- End of application. Normally, never occur. #- Could jump on Software Reset ( B 0x0 ).

#---------------------------------------------------------------- End: B End .end

链接脚本文件ldscript: SECTIONS {

. = 0x0;

.text : { *(.text) } .data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) } }

四、实验步骤:

1. 创建新的工程,工程名为:explasm;

2. 编写源代码文件并分别保存为randtest.c,init.s,random.s和ldscript,并加入工程里;

3. 按照编译、汇编器配置->链接器配置->调试器配置设置新工程;并编译链接工程; 4. 选择Debug菜单Remote Connect 进行连接软件仿真器,执行Download命令下载程序,并打开寄存器窗口。 5. 下载调试文件,打开memory/register/watch/variable/call stack窗口,单步执行程序,并通过以上窗口,跟踪程序运行,观察分析运行结果,通过实验学会使用Embest IDE进行应用程序的开发与调试。

/********************************* Init.s*****************************/ # ******************************************************* # * NAME : 44BINIT.S * # * Version : 10.April.2000 * # * Description: * # * C start up codes * # * Configure memory, Initialize ISR ,stacks * # * Initialize C-variables * # * Fill zeros into zero-initialized C-variables * # ******************************************************* #程序入口,arm汇编 #.arm

.global _start .text _start:

# --- Setup interrupt / exception vectors 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:

LDR sp, =0x00002000

#------------------------------------------------------------------------------ #- Branch on C code Main function (with interworking) #----------------------------------------------------

#- Branch must be performed by an interworking call as either an ARM or Thumb #- main C function must be supported. This makes the code not position- #- independant. A Branch with link would generate errors

#------------------------------------------------------------------------------ .extern main

ldr r0, = main mov lr, pc bx r0

#------------------------------------------------------------------------------ #- Loop for ever #---------------

#- End of application. Normally, never occur. #- Could jump on Software Reset ( B 0x0 ).

#------------------------------------------------------------------------------ End:

b End

.global __gccmain __gccmain:

mov pc, lr

.end

/***********************************Ldscript*****************************/ SECTIONS {

. = 0x0;

.text : { *(.text) }

.data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) } }

/***********************************random.s*****************************/ # Random number generator #

# This uses a 33-bit feedback shift register to generate a pseudo-randomly # ordered sequence of numbers which repeats in a cycle of length 2^33 - 1 # NOTE: randomseed should not be set to 0, otherwise a zero will be generated # continuously (not particularly random!). #

# This is a good application of direct ARM assembler, because the 33-bit # shift register can be implemented using RRX (which uses reg + carry).

# An ANSI C version would be less efficient as the compiler would not use RRX.

# AREA |Random$$code|, CODE, READONLY

.GLOBAL randomnumber

randomnumber: # on exit:

# a1 = low 32-bits of pseudo-random number # a2 = high bit (if you want to know it) LDR ip, seedpointer LDMIA ip, {a1, a2}

TST a2, a2, LSR#1 /* to bit into carry */ MOVS a3, a1, RRX /* 33-bit rotate right */ ADC a2, a2, a2 /* carry into LSB of a2 */ EOR a3, a3, a1, LSL#12 /* (involved!) */ EOR a1, a3, a3, LSR#20 /* (similarly involved!)*/ STMIA ip, {a1, a2}

MOV pc, lr

seedpointer:

.LONG seed

.DATA

.GLOBAL seed seed:

.LONG 0x55555555 .LONG 0x55555555

# END

/*********************************randtest.c*****************************/ /* Random number generator demo program

Calls assembler function 'randomnumber' defined in random.s */

//#include <stdio.h>

/* this function prototype is needed because 'randomnumber' is external */ extern unsigned int randomnumber( void );

int main() {

int i; int nTemp;

unsigned int random[10];

for( i = 0; i < 10; i++ ) {

nTemp = randomnumber(); random[i] = nTemp; }

return( 0 );

}

五、思考题:

从汇编语言中调用C函数:使用C语言完成一个随机数产生函数,通过汇编语言调用该函数,产生一系列随机数,存放到数组里面。

/*******************************Random.c*********************************/ int random() {

int i; int nTemp;

unsigned int random[10]; for( i = 0; i < 10; i++ ) {

nTemp = randomnumber(); random[i] = nTemp; }

return( 0 ); }

/********************************* Init.s*****************************/ # ******************************************************* # * NAME : 44BINIT.S * # * Version : 10.April.2000 * # * Description: * # * C start up codes * # * Configure memory, Initialize ISR ,stacks * # * Initialize C-variables * # * Fill zeros into zero-initialized C-variables * # ******************************************************* #程序入口,arm汇编 #.arm

.global _start .text _start:

# --- Setup interrupt / exception vectors 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:

LDR sp, =0x00002000

#------------------------------------------------------------------------------ #- Branch on C code Main function (with interworking) #----------------------------------------------------

#- Branch must be performed by an interworking call as either an ARM or Thumb #- main C function must be supported. This makes the code not position- #- independant. A Branch with link would generate errors

#------------------------------------------------------------------------------ .extern random @申明一个random外部函数,调用它 ldr r0, = random mov lr, pc

bl random @调用random函数

#------------------------------------------------------------------------------ #- Loop for ever #---------------

#- End of application. Normally, never occur. #- Could jump on Software Reset ( B 0x0 ).

#------------------------------------------------------------------------------ End:

b End .global __gccrandom __gccrandom:

mov pc, lr

.end

/***********************************Ldscript*****************************/ SECTIONS {

. = 0x0;

.text : { *(.text) } .data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) } }

/***********************************randtest.s***************************/ # Random number generator #

# This uses a 33-bit feedback shift register to generate a pseudo-randomly # ordered sequence of numbers which repeats in a cycle of length 2^33 - 1 # NOTE: randomseed should not be set to 0, otherwise a zero will be generated # continuously (not particularly random!). #

# This is a good application of direct ARM assembler, because the 33-bit # shift register can be implemented using RRX (which uses reg + carry).

# An ANSI C version would be less efficient as the compiler would not use RRX.

# AREA |Random$$code|, CODE, READONLY .GLOBAL randomnumber randomnumber: # on exit:

# a1 = low 32-bits of pseudo-random number # a2 = high bit (if you want to know it) LDR ip, seedpointer LDMIA ip, {a1, a2}

TST a2, a2, LSR#1 /* to bit into carry */ MOVS a3, a1, RRX /* 33-bit rotate right */

ADC a2, a2, a2 /* carry into LSB of a2 */ EOR a3, a3, a1, LSL#12 /* (involved!) */ EOR a1, a3, a3, LSR#20 /* (similarly involved!)*/ STMIA ip, {a1, a2} MOV pc, lr seedpointer:

.LONG seed .DATA

.GLOBAL seed seed:

.LONG 0x55555555 .LONG 0x55555555

# END

六、实验总结

通过实验我们能够得到,在实验中通过C调用汇编程序;还是汇编程序调用

C,其结果都是相同的。这两种编程方式都能达到我们期望中的实验效果,所以都是可取的编程方法。在这次实验中,要注意的是:我们所编写的程序是分为几个部分,在运行时,需要将其分开引入到一个工程中,使它们之间形成调用关系。同时在引进文件是需要选择所有文件类型,这与我们前边所执行程序时有所不同。同时,在实验中我学会了很多,也对软件有了更进一步的了解和认识。总的来说这次实验还是有所收获吧。

本文来源:https://www.bwwdw.com/article/sj34.html

Top