最近,在用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. 自制单片机之十五……可串行驱动LCD12864的应用

    在网上搜了一下,ST7920控制器的LCD产品可以提供8位,4位并行和串行接口可选,并行的控制接口的LCD较多,前面的贴子也介绍过,我们在这儿不说了,这儿我们讲的是串口控制LCD12864. 买了块S ...

  2. authbind start tomcat services as user with less that 1024 ports. linux常规用户使用tomcat的80端口

    Start tomcat services using authbind this will allow user to start ports less than 1024 we do not ne ...

  3. 【转】Android 定时器实现的几种方式和removeCallbacks失效问题详解--不错

    原文网址:http://blog.csdn.net/xiaanming/article/details/9011193 实现定时器有很多种方式,在这里我简单的介绍几种方式 (1)使用Handler + ...

  4. Hash Map (Hash Table)

    Reference: Wiki  PrincetonAlgorithm What is Hash Table Hash table (hash map) is a data structure use ...

  5. membership source code

    You can find their source code in codeplex at the ASP.NET source code. ExtendedMembershipProvider: h ...

  6. WPF与输入法冲突研究之二:汉字输入法会导致WPF程序的崩溃!

    如果是输入非汉字的数据信息,可以添加一下内容: xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCo ...

  7. NOTIFYICONDATA结构

    //农机调度项目代码 NOTIFYICONDATA m_notifyData; m_notifyIcon.ChangeIcon(IDI_PAUSE, _T("监控终端server已暂停&qu ...

  8. Unity怎样在Editor下运行协程(coroutine)

    在处理Unity5新的AssetBundle的时候,我有一个需求,须要在Editor下(比方一个menuitem的处理函数中,游戏没有执行.也没有MonoBehaviour)载入AssetBundle ...

  9. HDU2111 Saving HDU 【贪心】

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  10. Eclipse中Cannot find any provider supporting DES解决之道

    原文出处:http://blog.csdn.net/darwinchina/article/details/12037999 异常: Caused by: java.security.NoSuchAl ...