打印

请教用过汇编转C的高手 的

[复制链接]
楼主: dudongdao
手机看帖
扫描二维码
随时随地手机跟帖
21
dudongdao|  楼主 | 2009-8-7 08:56 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
可否混合处理~~   
我想进中断后去执行子程序,
执行完子程序后到主程序第一个函数处开始循环执行,
每次进中断后都重新初始化一次SP,中断转子程序处理完子函数后再初始化一次SP~ 然后到主函数头开始循环
不是等待中断~~

使用特权

评论回复
22
dudongdao|  楼主 | 2009-8-7 09:31 | 只看该作者
还有一个疑问~   
我主函数处定义了一个标号
while(1)
{
        #pragma asm
               
        _start:
        #pragma endasm
               
        SysTimerRun();//系统时间运行
        Process();  //常规事件处理
}
                #pragma asm
                MOV DPTR,#_start
                PUSH DPL
                PUSH DPH
                #pragma endasm
请问如何在其他文件中用这个标号呢? 我这么写编译不过~~  找不到标号~~

使用特权

评论回复
23
冷漠| | 2009-8-7 09:46 | 只看该作者
嘻嘻。
在主函数前定义PUBLIC  _start

在其它模块前说明EXTERN _start

也许还差点什么,不行我上机试试。行了告诉我们大家怎么做的,共享你的快乐。

使用特权

评论回复
24
dudongdao|  楼主 | 2009-8-7 11:50 | 只看该作者
冷漠大侠笑了~~   哈哈~~   其实你不冷漠的~~ 你多热心~~  
我去试试~~

使用特权

评论回复
25
dudongdao|  楼主 | 2009-8-7 11:58 | 只看该作者
我试了不行啊

使用特权

评论回复
26
dudongdao|  楼主 | 2009-8-7 17:55 | 只看该作者
搞定啦~~
所有函数还是放在主循环中,中断中只是建立标志位,如果遇到紧急处理的事件,就转到主循环第一个函数执行,办法由点笨,那就是要进入仿真环境,看一下SP初始化指针是多少,看一次主循环开始的地址是多少,
然后填到SP和DPTR,每次改程序都看一次~~   哈哈、~~  不过也凑合用了~~
        if(u8Flag)
        {
               
                #pragma asm
                MOV SP,#0x60
                MOV DPTR,#0BF6H
                PUSH DPL
                PUSH DPH
                SETB ES
                RETI
                #pragma endasm
        }

使用特权

评论回复
27
冷漠| | 2009-8-8 12:46 | 只看该作者
我试过了,好好的程序。  没不通过呀?

再检查检查你有什么地方不对。  起始堆栈SP和起始地址_start根本不用调试环境下确定。程序设定即可。

#pragma src
#include <reg52.h>

#define uchar unsigned char

uchar  SP_BACK;

void main()   
{
  SP_BACK=SP;
while(1)
{
        #pragma asm
   _start:
      // ;MOV SP_BACK,SP
        #pragma endasm
               
     //   SysTimerRun();//系统时间运行
      //  Process();  //常规事件处理
}
}

void  comm(void) interrupt  4
{
   #pragma asm
    MOV SP,SP_BACK
    MOV DPTR,#_start
    PUSH DPL
    PUSH DPH
    #pragma endasm
}

使用特权

评论回复
28
冷漠| | 2009-8-8 12:56 | 只看该作者
C:0x0000    020026   LJMP     STARTUP1(C:0026)
   157:           MOV SP,SP_BACK
   158: ;     MOV DPTR,#_start
C:0x0003    850881   MOV      SP(0x81),SP_BACK(0x08)
   159:           MOV DPTR,#_start
   160: ;     PUSH DPL
C:0x0006    900011   MOV      DPTR,#0x0011
   161:           PUSH DPL
   162: ;     PUSH DPH
C:0x0009    C082     PUSH     DPL(0x82)
   163:           PUSH DPH
   164: ;     #pragma endasm
   165: ; }
   166:                         ; SOURCE LINE # 36
C:0x000B    C083     PUSH     DPH(0x83)
   167:         RETI     
C:0x000D    32       RETI     
   115:         MOV     SP_BACK,SP
   116: ?C0001:
   117: ; while(1)
   118:                         ; SOURCE LINE # 11
   119: ; {
   120:                         ; SOURCE LINE # 12
   121: ;         #pragma asm
   122: ;                  
   123:            
   124: ;    _start:
   125:           _start:
   126: ;       // ;MOV SP_BACK,SP
   127:            
   128: ;  
   129:            
   130: ;         #pragma endasm
   131: ;                  
   132: ;      //   SysTimerRun();//系统时间运行
   133: ;       //  Process();  //常规事件处理
   134: ; }
   135:                         ; SOURCE LINE # 22
C:0x000E    858108   MOV      SP_BACK(0x08),SP(0x81)
   136:         SJMP    ?C0001
C:0x0011    80FE     SJMP     C0001(C:0011)
   137:         RET      
   138: ; END OF main
   139:  
   140: CSEG    AT  00023H
C:0x0013    22       RET      
C:0x0014    00       NOP      
C:0x0015    00       NOP      
C:0x0016    00       NOP      
C:0x0017    00       NOP      
C:0x0018    00       NOP      
C:0x0019    00       NOP      
C:0x001A    00       NOP      
C:0x001B    00       NOP      
C:0x001C    00       NOP      
C:0x001D    00       NOP      
C:0x001E    00       NOP      
C:0x001F    00       NOP      
C:0x0020    00       NOP      
C:0x0021    00       NOP      
C:0x0022    00       NOP      
   141:         LJMP    comm
C:0x0023    020003   LJMP     COMM(C:0003)
    99:                 MOV     R0,#IDATALEN - 1
C:0x0026    787F     MOV      R0,#0x7F
   100:                 CLR     A
C:0x0028    E4       CLR      A
   101: IDATALOOP:      MOV     @R0,A
C:0x0029    F6       MOV      @R0,A
   102:                 DJNZ    R0,IDATALOOP
C:0x002A    D8FD     DJNZ     R0,IDATALOOP(C:0029)
   151:                 MOV     SP,#?STACK-1
   152: ; This code is required if you use L51_BANK.A51 with Banking Mode 4
   153: ; EXTRN CODE (?B_SWITCH0)
   154: ;               CALL    ?B_SWITCH0      ; init bank mechanism to code bank 0
C:0x002C    758108   MOV      SP(0x81),#SP_BACK(0x08)
   155:                 LJMP    ?C_START
C:0x002F    02006D   LJMP     C_START(C:006D)
    94: INITEND:        LJMP    MAIN
    95:  
    96: $IF (XBANK = 0)
C:0x0032    02000E   LJMP     MAIN(C:000E)

使用特权

评论回复
29
dudongdao|  楼主 | 2009-8-8 13:34 | 只看该作者
都放同一个文件可以的,我是在串口C文件里边调用主C文件里边的标号,不对,用了你说的 PUBLICK
EXTERN   你这个怎么没用PUBLICK呢

使用特权

评论回复
30
冷漠| | 2009-8-8 17:33 | 只看该作者
分2个文件也通过呀。   第一个主文件用C写的 TEST.SRC
; test.SRC generated from: test.c
; COMPILER INVOKED BY:
;        C:\Keil\C51\BIN\C51.EXE test.c OPTIMIZE(6,SPEED) BROWSE ORDER DEBUG OBJECTEXTEND

$NOMOD51

NAME        TEST

SP        DATA        081H
DPL        DATA        082H
DPH        DATA        083H

?PR?main?TEST        SEGMENT CODE
?DT?TEST             SEGMENT DATA
        EXTRN        CODE (?C_STARTUP)
        PUBLIC        SP_BACK
        PUBLIC        main
public  _start           ;注意这里添加的语句****************

        RSEG  ?DT?TEST
        SP_BACK:   DS   1
; #pragma src
; #include <reg52.h>
; #include <stdio.h>
; #define uchar unsigned char
;
; uchar  SP_BACK;
;
; void main()   

        RSEG  ?PR?main?TEST
main:
                        ; SOURCE LINE # 8
; {
                        ; SOURCE LINE # 9
;   SP_BACK=SP;
                        ; SOURCE LINE # 10
        MOV          SP_BACK,SP
?C0001:
; while(1)
                        ; SOURCE LINE # 11
; {
                        ; SOURCE LINE # 12
;         #pragma asm
;   _start:
          _start:
;      
          
;         #pragma endasm
;                 
;      //   SysTimerRun();//系统时间运行
;       //  Process();  //常规事件处理
; }
                        ; SOURCE LINE # 20
        SJMP         ?C0001
        RET         
; END OF main

        END

使用特权

评论回复
31
冷漠| | 2009-8-8 17:40 | 只看该作者
第2个文件用汇编写的:comm.a51 (也是由comm.c改的。)

$NOMOD51
NAME        COMM

EXTRN  CODE(_start)    ;注意这2条添加的语句**********
EXTRN  DATA(SP_BACK)

SP        DATA        081H
DPL        DATA        082H
DPH        DATA        083H

?PR?comm?COMM        SEGMENT CODE
        PUBLIC        comm

CSEG        AT        00023H
        LJMP        comm

        RSEG  ?PR?comm?COMM
        USING        0
comm:
          MOV SP,SP_BACK
          MOV DPTR,#_start
          PUSH DPL
          PUSH DPH
          RETI        
    END

把TEST.SRC和COMM.A51放在同一个项目里编译连接。一样!

使用特权

评论回复
32
dudongdao|  楼主 | 2009-8-8 18:25 | 只看该作者
谢谢冷漠大侠~~
我试验了一下,出现警告了,运行也不正常,警告如下~~
*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
    SYMBOL:  _START
    MODULE:  .\output\serial.obj (SERIAL)
*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
    SYMBOL:  M_U8SPBACKUP
    MODULE:  .\output\serial.obj (SERIAL)
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
    SYMBOL:  M_U8SPBACKUP
    MODULE:  .\output\serial.obj (SERIAL)
    ADDRESS: 0148H
*** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL
    SYMBOL:  _START
    MODULE:  .\output\serial.obj (SERIAL)
    ADDRESS: 014BH

我的定义在主函数中:
    #pragma asm

public  _start  
    #pragma endasm


//#include <REG52.h>
#pragma src

#include "STC12C5410AD.H"
#include "absacc.h"

#include "Cfg.H"
#include "define.H"

#include "timer.H"
#include "function.H"
#include "flash.h"
#include "iic.h"
#include "serial.h"
#include "global.H"
#include "mt9d11.h"
#include "pd16835.h"
#include "eeprom.h"
#include "process.h"
#include "mcuinit.h"
   
    #pragma asm

public  _start  
    #pragma endasm


void main(void)
{
        InitMcuHardWare();  
        InitSystem();
       
        #if(DUBG == 1)
        SendString("STARRESET");
        #endif

        m_u8SpBackUp = SP;
        EA = 1;
       
    #pragma asm
    _start:
    #pragma endasm
       
        LED_ON();
        while(1)
        {
                SysTimerRun();//系统时间运行
                Process();  //常规事件处理
        }
}
在串口函数中:
#pragma asm
EXTRN  CODE(_start)
EXTRN  DATA(m_u8SpBackUp)
#pragma endasm
        if(u8Flag)
        {
                #pragma asm
                MOV SP,m_u8SpBackUp
                MOV DPTR,#_start
                PUSH DPL
                PUSH DPH
                SETB ES
                RETI
                #pragma endasm
        }


很奇怪后来又编译不过了,你可以给出C的形式吗~~  
比如你的主函数C立面是加的什么,然后串口C部分加了哪些命令,就是你最原始的文件,你给出的是编译器处理过的,有些晕乎~

使用特权

评论回复
33
冷漠| | 2009-8-8 19:35 | 只看该作者
本帖最后由 冷漠 于 2009-8-8 19:36 编辑

这是TEST.C文件

#pragma src
#include <reg52.h>

#define uchar unsigned char

uchar  SP_BACK;

void main()   
{
  SP_BACK=SP;
while(1)
{
        #pragma asm
  _start:
      
        #pragma endasm
               
     //   SysTimerRun();//系统时间运行
      //  Process();  //常规事件处理
}
}

使用特权

评论回复
34
冷漠| | 2009-8-8 19:42 | 只看该作者
这是comm.c文件:

#pragma src(comm.a51)
#include <reg52.h>
#define uchar unsigned char

extern  uchar  SP_BACK;

void  comm(void) interrupt  4
{

   #pragma asm
    MOV SP,SP_BACK
    MOV DPTR,#_start
    PUSH DPL
    PUSH DPH
    #pragma endasm
}

使用特权

评论回复
35
dudongdao|  楼主 | 2009-8-9 00:27 | 只看该作者
还是不行,请问#pragma src
是什么意思呢~~~

使用特权

评论回复
36
冷漠| | 2009-8-9 10:22 | 只看该作者
本帖最后由 冷漠 于 2009-8-9 10:26 编辑

很简单。先把我的2个文件单独分别编译,是否通过?当然行。由此产生了2个汇编文件:
TEST.SRC
COMM.A51
能通过吧。到此没有问题吧?然后一个一个汇编,得到2个OBJ文件:TEST.OBJ,COMM.OBJ。做到此没问题吧。链接2个OBJ文件即可。做到此完成了重要的第一阶段。有什么问题告知:那是我的问题。

第二阶段:第一阶段先把2个文件连接成的简单框架做通,然后把自己的函数做在另一个新打开文件里,假设FUNC.C,甚至FUNC1.CFUNC2.C......单独编译、查错,注意不是编译+连接!产生正确的一个或多个FUNCX.OBJ文件。一个一个通过。当所有的函数都编译无错之后,最后再把这些**.obj连接起来。

把复杂的事情分解为简单的独立部件一步一步完成,没有做不到的事!这也是编程分模块化工作的宗旨吧。

正好像你把整个程序(工程项目)如果分4个人去完成,是不是要简单得多?那你就分成4个模块,一个一个独立完成。

否则,一个人做一大摊,A、B、C、D一块来,谁知道错在哪?

使用特权

评论回复
37
冷漠| | 2009-8-9 10:35 | 只看该作者
本帖最后由 冷漠 于 2009-8-9 10:37 编辑

呵呵:  m_u8SpBackUp 缺少定义,没有定义就使用了。

我在TEST.C中定义过的:uchar  SP_BACK;

使用特权

评论回复
38
dudongdao|  楼主 | 2009-8-9 15:04 | 只看该作者
我贴一个图出来,请冷漠大侠看一下,单独编译没错,链接的时候出错。

使用特权

评论回复
39
冷漠| | 2009-8-9 19:44 | 只看该作者
你贴的图自己看得清吗?我只能看出斑斑点点。不知是不是我机器落后还是什么原因,反正老版论坛贴图显示清清楚楚,和本机显示效果一样。换了新版,字体、贴图显示都明显不如原来感觉好。还要求网友“慢慢适应、习惯”?反正人可以习惯一切,包括倒退。

原来的21IC论坛风格独特,看上去舒服。全国没发现有同样风格的。绝对不愧是“全国两千万工程师汇聚的地方”。现在的新版风格和其它绝大多数论坛一样了。看上去也不是21IC了。好像还不如老HOT的个人“嵌入式公社”网站做得好。

记得以前旧版看“呆板书生”的贴图,看上去又清楚,又漂亮,连背景暗花都显示出来了。现在回头再看那张原图,连字都显示不清。和你的贴图显示效果一样。

实在我计算机不差,刚换的HP双核,独立显卡,WIN_XP正版。新版用着真别扭。是不是我什么地方设置不对?还是就这样了!

使用特权

评论回复
40
dudongdao|  楼主 | 2009-8-9 20:25 | 只看该作者
冷漠,用鼠标点击一下图片,等几秒,能出来个稍微大点的,用鼠标滚轮能调节大小的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则