《电子技术应用》
您所在的位置:首页 > 模拟设计 > 业界动态 > 飞思卡尔hcs08 c语言之混和编程

飞思卡尔hcs08 c语言之混和编程

2017-07-23
关键词: 汇编语言

混和编程

1)内嵌汇编

HCS08 C 语言提供一个很有用的功能,内嵌汇编。凡是C语言程序段能出现的地方汇编语言源程序都可以出现,但是汇编语言源程序必需位于一个C语言函数中。

语法格式

1) "asm" <汇编指令> ";" ["/*" 注释 "*/"]

双引号中的内容为关键字,方括号中的内容为可选项。

例如:

asm sta COPCTL;   /* 喂狗 */

2) "asm" "{"

<汇编指令 1> [";" 注释]

<汇编指令 2> [";" 注释]

"}"

要求:大括号内每条汇编指令占一行;标号以“:”结尾占一行;注释以“;”开始;可以用变量名访问全局变量和C 函数中的局部变量。汇编语言结束前要保证堆栈内容与汇编开始前一致。

例如:用内嵌汇编方法实现统计字符串中字符的个数。

int strlen (char *str)

/*** 'str' 参数由堆栈传递. 函数返回字符串'str'的长度

假定字符串的长度小于256!

*/

{

asm {

LDHX str      ; 装入指针

CLRA           ; 初始化计数器

BRA test      ; 跳到test

loop:

AIX #1        ; 指针加1

INCA          ; 计数器加1

test:

TST 0,X      ; 字符串是否结束?

BNE loop     ; 下一字符

CLRX          ; 返回值在 X:A(参见后文)

};

/* 这里可以继续写 C 语言程序段 */

}

2)混和调用

混和调用指的是C语言函数调用汇编语言函数和汇编语言函数调用C语言函数。实现混和调用要解决两个问题1:常量和变量的相互访问;2调用协议

1常量和变量的相互访问

C 语言函数访问汇编语言常量、变量

在汇编语言源程序中采用汇编语法定义变量和常量;在C语言中把这些变量、常量声明为外部常量变量,即可以用变量、常量名来访问。汇编器和编译器敏感段名的大小写。

例如:

汇编源程序中

XDEF ASMData, ASMConst ;声明 ASMData, ASMConst 可以在模块外访问

MyData: SECTION

ASMData: DS.W 1 ; 定义变量

MyConst: SECTION

ASMConst: DC.W $44A6 ; 定义常量

在 C 语言源程序中

#pragma DATA_SEG MyData /* 定义变量段 */

extern int ASMData; /* 变量 ASMData 是外部模块声明的 */

#pragma DATA_SEG DEFAULT /* 返回默认变量段 */

#pragma CONST_SEG MyConst /* 定义常数段 */

extern const int ASMConst; /* 常量 ASMConst 是外部模块声明的*/

#pragma CONST_SEG DEFAULT /*返回默认常数段   */

汇编语言访问C语言变量、常量

在C语言中用标准格式定义常量、变量,在汇编语言中声明这些常量变量是外部定义即可。

例如:

在C语言源文件中:

unsigned int CData; /* 定义变量 */

unsigned const int CConst; /* 定义常量 */

在汇编语言源文件中:

XREF CData ; 外部声明的变量

XREF CConst; 外部声明的常量

使用:

LDD CConst

STD CData

2)调用协议

调用协议,即函数参数传递和返回值的协议。对于HC08和HCS08调用协议是不同的。

HC08 参数传递:调用者函数把所需参数从左到右依次入栈,调用结束后由调用者函数从堆栈中清除传递的参数。在函数传递的是值参数的情况下,如果最后一个参数长度为2字节,则用X:A寄存器对传递;如果最后一个参数长度为1字节且倒数第2个参数长度超过1字节,则最后一个参数用寄存器A传递;如果最后一个参数长度为1字节且倒数第2个参数长度也是1字节,则最后一个参数用寄存器X传递,倒数第2个参数用寄存器A传递;

HCS08返回值:函数返回值总是在寄存器中,根据返回值的类型不同,而采用不同的寄存器

返回值类型

   

寄存器

   

char (signed 或 unsigned)

   

A

   

int (signed 或 unsigned)

   

H:X

   

pointers/arrays(指针/数组)

   

H:X

   

function pointers(函数指针)

   

H:X

   

如果返回值的长度超过2字节,则在H:X存放返回值的地址。

例如:写一段C语言源程序,然后把它编译为汇编语言,观察调用规则

#include /* 为了包含中断允许宏定义*/

#include

unsigned char r;

unsigned char f1(unsigned char v1,unsigned char v2,unsigned char v3,unsigned char v4) {

    v1+=1;

     v2+=1;

     v3+=1;

     v4+=1;

     return(v4);

}

void f0(void) {

        r=f1(4,9,6,3);

    }

void main(void) {

   EnableInterrupts; /*中断允许 */

               f0();

   for(;;) {

     __RESET_WATCHDOG(); /* 喂狗 */

   }  

}

在C语言源程序中f0函数调用f1函数,传递参数并有返回值

函数f1编译后的汇编语言

PSHA        ; 有参数用X、A传递,入栈保存防止破坏

PSHX

     TSX          ; X=SP+1

     INC    5,X   ; v1+=1,参数v1在sp+6处

     INC    4,X   ; v2+=1; 参数v2在sp+5处

     INC    1,X   ; v3+=1; 参数v3在A中,被本函数入栈

    INC    ,X    ; v4+=1; 参数v4在X中,被本函数入栈

     LDA    ,X    ; return(v4);返回值在A中

     AIS    #2    ; 调整堆栈指针,指向返回地址

     RTS    ; 返回f0函数

函数f0编译后的汇编语言

     LDA    #4

     PSHA       ; 参数v1入栈

     LDA    #9

     PSHA       ; 参数v2入栈

     LDA    #6   ; 参数v3用A传递

     LDX    #3   ; 参数v4用X传递

     BSR    f1   ; 调用函数f1

     AIS    #2   ; 清除传递的参数

     STA    r    ; 保存返回值

     RTS        ; 返回main函数

Main函数编译后的汇编语言

CLI   

BSR    f0

L3:     

STA    _COPCTL

BRA    L3

只要遵循以上调用规则,就可以实现用C函数和汇编函数的相互调用。调用时使用对方定义的函数名。

16.2.5启动代码

在启动main函数之前HCS08 C 语言会自动运行一段启动代码,进行硬件初始化和建立C语言的运行环境。起动代码一般由编译器自动生成,也可以由用户自写的启动代码替代自动生成的启动代码。启动代码的名字为start08.c,它的主要工作是:

l          禁止中断

l          从ROM到RAM复制并初始化数据

l          未初始化的数据区域清零

l          为堆栈分配并初始化堆栈

l          如果用到堆,创建并初始化堆

l          允许中断

l          调用main()函数

分类:


本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306116;邮箱:aet@chinaaet.com。