最近,在用keil 写一个小程序时,想实践一下从汇编调用 C语言函数,我们都知道C语言调用汇编函数讨论得较多,但反过来,从汇编中调用C语言的函数未见深入分析;在开始的时候,还是忽视了一个问题,就是对现场的保护和还原,以导于程序跑飞。

下面的一个小的测试用例,主要作用是:从C语言程序中调用一个用汇编写的名为int LEDFLASH(int a, int b)。并从该汇编函数中,反过来调言用C语言实现的delay()延时程序。最后的结果是:由P2口控制的LED灯出现闪烁的现象。
 
 C语言源程序所在文件名为:user.c,C语言源程序如下:
 #include <reg52.h>
     void delay(int,int);
 int LEDFLASH(int a,int b);
 void test();
 void main()
 {
    P2 = 0xff;
   while(1)
   LEDFLASH(0xff00,0x0007);
 }
 
 void delay(int a,int b)
 {
  int i,j;
  for(i = 0;i<a;i++)
   for(j= 0;j<b;j++)
    ;
 }
 void test()
 {
   delay(200,245);
   P2 = ~P2;
   delay(201,300);
 }
 
/***************************/
下面是名为afun.asm 的文件,其中实现对LED灯的控制和反调C语言函数。
 
Name TEST1
 
EXTRN CODE(_delay)
 
?PR?LEDFLASHC?XY SEGMENT CODE
 
PUBLIC _LEDFLASH
 
RSEG ?PR?LEDFLASHC?XY 
 
using 0
 
_LEDFLASH:
 
  mov a,r7
  add a,r5
  mov r7,a
  mov a,r6
  add a,r4  ;接收参数并计算
 
  mov r2,ar7
  mov r1,a  ;保存计算结果
 
  push ar7
  push ar6
  push ar5
  push ar4
  push ar3
  push ar2
  push ar1
  push ar0  ;保护现场
 
  mov r7,#200
  mov r6,#0
  mov r5,#200
  mov r4,#0    ;传递延时参数
   
 
  call _delay   ;调用C语言写的延时函数
  pop ar0
  pop ar1
  pop ar2
  pop ar3
  pop ar4
  pop ar5
  pop ar6
  pop ar7   ;还原现场
  mov P2,r2
 
 
  push ar7
  push ar6
  push ar5
  push ar4
  push ar3
  push ar2
  push ar1
  push ar0
 
  mov r7,#200
  mov r6,#0
  mov r5,#200
  mov r4,#0
 
  
 
  call _delay
  pop ar0
  pop ar1
  pop ar2
  pop ar3
  pop ar4
  pop ar5
  pop ar6
  pop ar7
  
  mov a,r2
  cpl a
   
  mov P2, a
  ;MOV P1,r1
  
  RET
  END
 
以上汇编函数中调用C语言函数容易被忽视的地方是在调用(call _delay)时,往往容易遗漏对现场的保护,即对CPU寄存器的保护;在汇编调用C语言实现的delay(int,int)函数前,先对cpu的寄存器进行入栈,调用完后,再进行出栈还原现场。这是因为从汇编调用C语言函数时,C语言函数没有替汇编完成该汇编函数要用到的寄存器(含状态寄存器)等的保护。如果不注意这点,写出来的程序将出现意外。上面例的代码还可以优化,由于只是做一个测试,未进行优化。 在网上也会看到其它少量的讨论从汇编调用C语言函数的文章,还未见有对寄存器进行保护和还原的。

keil or c51 汇编调用c语言函数 容易忽视的问题的更多相关文章

  1. 从linux0.11中起动部分代码看汇编调用c语言函数

    上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...

  2. Matlab调用C语言函数

    Matlab调用C语言函数 如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数:double add(double x, double y) { return x + y ;}现在我想要在 ...

  3. C语言中递归什么时候能够省略return引发的思考:通过内联汇编解读C语言函数return的本质

    事情的经过是这种,博主在用C写一个简单的业务时使用递归,因为粗心而忘了写return.结果发现返回的结果依旧是正确的.经过半小时的反汇编调试.证明了我的猜想,如今在博客里分享.也是对C语言编译原理的一 ...

  4. python 调用 C语言函数

    python可以直接调用C语言的函数,本文记录用ctypes调用c语言的方法. test.c #include <stdio.h> int test(char *temp) { print ...

  5. [转]在C#中调用C语言函数(静态调用Native DLL,Windows & Microsoft.Net平台)

    原文:https://blog.csdn.net/yapingxin/article/details/7288325 对于不太了解.Net的人,如果想要了解.Net,我必须给他介绍P/Invoke.P ...

  6. 在Linux上实现Python调用C语言函数

    一般思路 Python中内置ctypes库,需调用c编译成的.so文件来实现函数调用. 假设我们所需调用的c文件名为test.c,文件里有我们需要的函数func(x,y). 将.c文件编译成 .so文 ...

  7. java jni 调用c语言函数

    今日在hibernate源代码中遇到了native关键词,甚是陌生,就查了点资料,对native是什么东西有了那么一点了解,并做一小记. native关键字说明其修饰的方法是一个原生态方法,方法对应的 ...

  8. python 调用c语言函数

    虽然python是万能的,但是对于某些特殊功能,需要c语言才能完成.这样,就需要用python来调用c的代码了 具体流程: c编写相关函数 ,编译成库 然后在python中加载这些库,指定调用函数. ...

  9. 【Python】python 调用c语言函数

    虽然python是万能的,但是对于某些特殊功能,需要c语言才能完成.这样,就需要用python来调用c的代码了具体流程:c编写相关函数 ,编译成库然后在python中加载这些库,指定调用函数.这些函数 ...

随机推荐

  1. Keil C51 vs 标准C

    深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型及存储区域 存储模式 存储器类型声明 变量类 ...

  2. 使用NUnit进行项目的单元测试

    using System; using System.Collections; using System.Collections.Generic; using NUnit.Framework; nam ...

  3. HTTP 504 错误

    5xx(服务器错误)这些状态代码表示,服务器在尝试处理请求时发生内部错误.这些错误可能是服务器本身的错误,而不是请求出错. 504(网关超时) 服务器作为网关或代理,未及时从上游服务器接收请求. 50 ...

  4. Android Toast简介

    Toast是Android中一种提供给用户简短信息的视图,该视图已浮于应用程序之上的形式呈现给用户.因为它并不获得焦点,即使用户正在输入什么也不会受到影响.它的目标是尽可能以不显眼的方式,使用户看到你 ...

  5. UVA11456--dp,LIS

    这道题是个不错的dp题,可以放在区域赛签到题或者铜牌题. 这题希望火车序列最长,我们可以想到,如果一辆车ai如果能被放上去,先不管之前放上了多少辆车,以及这辆车是什么时候放上去的,但是我们可以确定的是 ...

  6. js为鼠标添加右击事件

    <script language="javascript">  /*document.oncontextmenu=Youji;*/  //为当前文档添加鼠标右击事件,防 ...

  7. Android Studio新手全然指引

    Android Studio新手全然指引 @author ASCE1885的 Github 简书 微博 CSDN Android Studio的下载及安装 假设你的电脑能够FQ,那么请直接到Andro ...

  8. linux core dump学习

    1. core dump是什么? core dump又叫核心转储,当操作系统收到特定的signal时, 会生成某个进程的core dump文件.这样程序员可以根据 已经生成的core dump文件来d ...

  9. [RxJS] Updating Data with Scan

    You often need to update the data flowing through the stream with custom logic based on what you nee ...

  10. 2014牡丹江——Domination

    题目链接 题意: 给一个n*m的矩阵,每天随机的在未放棋子的格子上放一个棋子.求每行至少有一个棋子,每列至少有一个棋子的天数的期望  (1 <= N, M <= 50). 分析: 比較明显 ...