积分规则 网站地图 帮助中心    
嵌入式软件 单 片 机 DSP 存储器 传感控制 光电显示
嵌入式硬件 CPLD/FPGA SOPC AD/DA 接口电路 模拟设计
I C设计 通信产品 汽车电子 电源产品 消费电子 数控系统
工业控制 军工/航天 安防产品 医疗电子 计算机外设 测试测量
供应 I C
求购 公司库

  IC 求购 销售 公司 论文 DATASHEET 参考设计 论坛
当前位置: 电子技术 >> 嵌入式硬件 >> MIPS
  相关分类: 相关文章 | ARM | 新产品 | 下载 | MIPS | X86 |
MIPS 寄存器约定
 
作者:陈怀临翻译   来源:嵌入式技术网    点击数:1195   更新时间:2007-1-26
您可以添加到网摘 让更多人关注此文章:

    
寄存器约定

对于在一个CPU上进行开发,掌握其工作的CPU的寄存器约定是非常重要的。

MIPS体系结构提供了32GPR(GENERAL PURPOSE REGISTER)。这32个寄存器的用法大致如下:

REGISTER NAME USAGE
$0 $zero 常量0(constant value 0)
$2-$3 $v0-$v1 函数调用返回值(values for results and expression evaluation)
$4-$7 $a0-$a3 函数调用参数(arguments)

$8-$15 $t0-$t7 暂时的(或随便用的)
$16-$23 $s0-$s7 保存的(或如果用,需要SAVE/RESTORE)(saved)
$24-$25 $t8-$t9 暂时的(或随便用的)
$28 $gp 全局指针(Global Pointer)
$29 $sp 堆栈指针(Stack Pointer)
$30 $fp 帧指针(Frame Pointer)
(BNNfp is stale acutally, and can be simply used as $t8)
$31 $ra 返回地址(return address)

对一个CPU的寄存器约定的正确用法是非常重要的。当然对C语言开发者不需要关心,因为COMPILERTAKE CARE。但对于KERNEL的开发或DRIVER开发的人就**必须**清楚。

一般来讲,你通过objdump -d可以清醒的看到寄存器的用法。

下面通过我刚才写的一个简单例子来讲解:

~/ vi Hello.c
"Hello.c" [New file]
/* Example to illustrate mips register convention
* -Author: BNN
* 11/29/2001
*/

int addFunc(int,int);
int subFunc(int);

void main()
{

int x,y,z;
x= 1;
y=2;
z = addFunc(x,y);
}


int addFunc(int x,int y)
{
int value1 = 5;
int value2;

value2 = subFunc(value1);
return (x+y+value2);

}

int subFunc(int value)
{
return value--;
}

上面是一个C程序,main()函数调用一个加法的子函数。让我们来看看编译器是如何产生代码的。

~/bnn:74> /bin/mips-elf-gcc -c Hello.o Hello.c -mips3 -mcpu=r4000 -mgp32 -mfp32 -O1

~/bnn:75> /bin/mips64-elf-objdump -d Hello.o
Hello.o: file format elf32-bigmips
Disassembly of section .text:

/* main Function */
0000000000000000
:
/*create a stack frame by moving the stack pointer 8
*bytes down and meantime update the sp value
*/
0: 27bdfff8 addiu $sp,$sp,-8
/* Save the return address to the current sp position.*/
4: afbf0000 sw $ra,0($sp)
8: 0c000000 jal 0

/* nop is for the delay slot */
c: 00000000 nop
/* Fill the argument a0 with the value 1 */
10: 24040001 li $a0,1
/* Jump the addFunc */
14: 0c00000a jal 28
/* NOTE HERE: Why we fill the second argument
*behind the addFunc function call?
* This is all about the "-O1" compilation optimizaiton.
* With mips architecture, the instruciton after jump
* will also be fetched into the pipline and get
* exectuted. Therefore, we can promise that the
* second argument will be filled with the value of
* integer 2.
*/
18: 24050002 li $a1,2
/*Load the return address from the stack pointer
* Note here that the result v0 contains the result of
* addFunc function call
*/
1c: 8fbf0000 lw $ra,0($sp)
/* Return */
20: 03e00008 jr $ra
/* Restore the stack frame */
24: 27bd0008 addiu $sp,$sp,8

/* addFunc Function */
0000000000000028 :
/* Create a stack frame by allocating 16 bytes or 4
* words size
*/
28: 27bdfff0 addiu $sp,$sp,-16
/* Save the return address into the stack with 8 bytes
* offset. Please note that compiler does not save the
* ra to 0($sp).
*Think of why, in contrast of the previous PowerPC
* EABI convention
*/
2c: afbf0008 sw $ra,8($sp)
/* We save the s1 reg. value into the stack
* because we will use s1 in this function
* Note that the 4,5,6,7($sp) positions will then
* be occupied by this 32 bits size register
*/
30: afb10004 sw $s1,4($sp)
/* Withe same reason, save s0 reg. */
34: afb00000 sw $s0,0($sp)
/* Retrieve the argument 0 into s0 reg. */
38: 0080802d move $s0,$a0
/* Retrieve the argument 1 into s1 reg. */
3c: 00a0882d move $s1,$a1
/* Call the subFunc with a0 with 5 */
40: 0c000019 jal 64
/* In the delay slot, we load the 5 into argument a0 reg
*for subFunc call.
*/
44: 24040005 li $a0,5
/* s0 = s0+s1; note that s0 and s1 holds the values of
* x,y, respectively
*/
48: 02118021 addu $s0,$s0,$s1
/* v0 = s0+v0; v0 holds the return results of subFunc
*call; And we let v0 hold the final results
*/
4c: 02021021 addu $v0,$s0,$v0
/*Retrieve the ra value from stack */
50: 8fbf0008 lw $ra,8($sp)
/*!!!!restore the s1 reg. value */
54: 8fb10004 lw $s1,4($sp)
/*!!!! restore the s0 reg. value */
58: 8fb00000 lw $s0,0($sp)
/* Return back to main func */
5c: 03e00008 jr $ra
/* Update/restore the stack pointer/frame */
60: 27bd0010 addiu $sp,$sp,16

/* subFunc Function */
0000000000000064 :
/* return back to addFunc function */
64: 03e00008 jr $ra
/* Taking advantage of the mips delay slot, filling the
* result reg v0 by simply assigning the v0 as the value
*of a0. This is a bug from my c source
* codes--"value--". I should write my codes
* like "--value", instead.
68: 0080102d move $v0,$a0


希望大家静下心来把上面的代码看懂。一定要注意编译器为什么在使用s0s1之前要先把她们SAVE起来,然后再RESTORE,虽然在这个例子中虽然main 函数没用s0s1


另外的一点是:由于我们加了“-O1”优化,编译器利用了“delay slot"来执行那些必须执行的指令,而不是简单的塞一个”nop"指令在那里。非常的漂亮。

最后,考大家一个问题,为了使得大家更加理解寄存器的用法:

*在写一个核心调度context switch()例程时,我们需要SAVE/RESTORE$t0-$t7吗?如果不,为什么?

*在写一个时钟中断处理例程时,我们需要SAVE/RESTORE$t0-$t7吗?如果是,为什么?


相关文章
· 科技奥运与计算机技术的应用[271]
· Electromedical[2572]
· 患者监控[2618]
· 基于TMS320LF2407A DSP的心电监护系统研究[3035]
· 用S3C2410实现三导联远程心电监护系统[2974]
热门评论排行
·VHDL设计中电路简化问题的
·江苏嵌入式Linux教育培训
·锐极LINUX驱动培训班定于
·基于实时操作系统μC/OS-
·ARM处理器应用开发4步骤

文章评论
    没有任何评论
*只显示最新10条评论。评论内容只代表网友观点,与本站立场无关。更多评论
发表评论
  * 请先[登陆]再进行评论,谢谢。
评分: 1分 2分 3分 4分 5分
内容: *
发帖须知:
一.所发文章必须遵守《互联网电子公告服务管理规定》;
二.严禁发布供求代理信息,公司介绍,产品信息等广告宣传信息;
三.严禁恶意重复发帖;
四.严禁对个人,实体,民族,国家等进行漫骂,污蔑,诽谤。
 
热点新闻 [更多]
 
首尔半导体就日亚(NICHIA)专利
MIPS 科技授权国家集成
美国微芯科技公司与安森美半导体拟以每
中嵌联盟嵌入式工程师俱乐部"
e-Shuttle与香港科技园携手
美国国家半导体推出业界首个传感器信号
PAC 2008 
Power Archite
2008上半年中国集成电路市场回顾
日本开发出接近人眼功能的新型电荷耦合
 
热门下载 [更多]
 
[ PCB设计] Protel99教程下载
[ ] 手把手学单片机20个例
[ ] 单片机做的智能台灯
[ ] 单片机入门书
[ ] linux系统移植开发文档
[ ] IC卡的读写程序
[ ] 8051单片机C语言彻底应用
[ 常用软件] 555定时器电路设计软件V1.2
[ 常用软件] 51定时器计算软件
[ ] ARM处理器应用开发4步骤
 
论坛新帖 [更多]
 
13×8的led屏一般用什么方...
[分享]选购家用稳压电源...
[分享]变频电源的外围配置要点...
dsp控制异步电机,加cpld...
请问一下,5000系列的DSP...
modbus与gsm连接,请问...
DSP信号处理配套MEMORY...
FPGA微处理器POWERPC...
[推荐]嵌入式3.5寸工业主板...
高级射频工程师(猎头职务-珠海...

 
赞助商 [更多]
 

ICP许可证号:[粤 05056597]
联系电话:010-82517432 82517615 传真: 010-82517615

版权所有 Copyright © 2006 嵌入式技术网