发新帖我要提问
123
返回列表
打印

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

[复制链接]
楼主: dudongdao
手机看帖
扫描二维码
随时随地手机跟帖
41
冷漠| | 2009-8-9 21:32 | 只看该作者 回帖奖励 |倒序浏览
本帖最后由 冷漠 于 2009-8-9 22:13 编辑

明白了。这是分2步实现的,你才做了第一步:
1、编译main.c,和 e.c 。是各自编译,编译后只能产生汇编文件,如果不经A51汇编不会产生OBJ文件,所以连接通不过。
#pragema SRC不会产生.obj文件,它只能产生汇编文件。
   这样你的main.c编译后产生main.src文件,e.c编译后产生comm.a51文件。

2、第二部你没做。把前2个C文件从项目中remove,项目中加入2个汇编文件main.src和comm.a51,还有SATARTUP.a51,共同汇编、链接,才是最终结果。
因为汇编后会得到3个OBJ文件:main.obj,comm.obj,startup.obj,连接器将其连接,这时PUBLI ,EXTRN,才起作用。

还有可以通过设定,使得上面2步化为 1 步,C编译后自动汇编**.src,  ** .a51文件,然后自动连接。并不好玩。因为你的汇编文件中途还要添加东西,不能全自动。所以还是一步一步来好。概念清楚。

可以看一下C51 编译器,A51宏汇编器,和BL51链接定位器教材。推荐电子工业出版社《Keil Cx51 V7.0单片机高级语言编程与uVision2应用实践》徐爱钧,彭秀华编著

使用特权

评论回复
42
dwq175| | 2009-8-10 09:14 | 只看该作者
LZ要用C就不要满脑子都是ASM了.
用C写的就不能实时响应?
C的中断响应跟ASM的中断响应也不会差多少啊!
是不是当事件发生就能处理才叫实时?ASM的中断响应也是要时间的.

使用特权

评论回复
43
冷漠| | 2009-8-10 11:07 | 只看该作者
本帖最后由 冷漠 于 2009-8-10 11:09 编辑

修改一下:
#pragma asm
  _start:
#pragma  endasm

改为  __asm  _start:

单条汇编语句,用__asm。注意是2条短划线。
再玩得好,直接在C语句前加标号即可,例如:
while(1)
{  
_start:    SysTimerRun();//系统时间运行
               .......
              ......
FLAGE_1:        Process();  //常规事件处理

)

但是需要后继一些处理。

使用特权

评论回复
44
huangqi412| | 2009-8-10 11:44 | 只看该作者
首先,,,干吗把汇编一对一翻译成C?   如果你翻译**,照字典一个个词翻译过来么???

使用特权

评论回复
45
huangqi412| | 2009-8-10 11:44 | 只看该作者
首先,,,干吗把汇编一对一翻译成C?   如果你翻译**,照字典一个个词翻译过来么???

使用特权

评论回复
46
dudongdao|  楼主 | 2009-8-10 20:35 | 只看该作者
42 楼的兄弟~  你没看懂我的问题啊~~  有疑问请说,或者给我一个C得解决方案,最好一句汇编都不加,我也想这样。

44 45楼的兄弟,我求的是一个解决问题的方法,现在找到最好的是C嵌入汇编。为什么要把汇编翻译成C呢,因为C好维护,好修改,也不能是一个一个词翻译的,如果可以的话,有了金山词霸,英语翻译都下岗了,谁不是英语翻译呢?

多谢冷漠大侠~~  看来冷漠大侠对KEIL研究的很透彻啊~~  我还是先按照原来的方法来了,等我看懂了再修改。我把问题想的简单了,一个C文件中定义了一个标号,能在另一个C文件中使用就这样,没想到设计到这么多编译连接的知识。

使用特权

评论回复
47
冷漠| | 2009-8-11 10:49 | 只看该作者
本帖最后由 冷漠 于 2009-8-11 10:54 编辑

呵呵。好不容易找到个课题,借此多学习一些知识呀。如果单独去看那些编译连接知识,回头就忘。现在回想起在学校学习时,老师照本宣科,其实他自己的没弄明白呢。否则应该举几个例子就好理解了。可是老师举不出来例子,结果到了毕业学生还是一头雾水。

再推荐一本《C语言详解》。看看什么叫名字的作用域。一个名字,包括标号。C中的标号只具有函数作用域,也就是说C语言环境下, A函数不可能使用到B函数中的标号!B函数中的标号对函数外部是不可见的。——但是汇编语言环境就可以。所以,你可以用C写主程序,但要实现由中断函数跳转到main( )函数中的标号地址位置,就必须最后把C经过汇编加工完成。

其实用C完全可以实现你的目标,书上到处有现成的例子,随手就可以拿来一个,只是跟别人学没什么意思罢了。举例:

1、定义全局变量 uchar  command_number;
2、main( )函数中有

switch(command_number)
{
case command_A:{  执行语句 }break;
case command_B:{         ...        }break;
case command_C:{         ...        }break;
...
default :  {   ...};
}

中断函数中有:
{
RS-232命令码接收;
ommand_number=接收的命令码; //command_A /B /C /...

中断程序最后:
#pragma asm
MOV SP,SP_BACK
MOV DPTR,# main
PUSH DPL
PUSH DPH
RETI
#pragma endasm
}

这样主函数用全C写,不用改。
中断函数用混合语言或者全汇编写。很简单。

使用特权

评论回复
48
dudongdao|  楼主 | 2009-8-11 19:30 | 只看该作者
冷漠大侠   我试验了一下,认不到main,提示编译错误

.\output\serial.src(873): error A45: UNDEFINED SYMBOL (PASS-2)

认不到这个标号~~  在串口声明了   extern void main(void);

使用特权

评论回复
49
冷漠| | 2009-8-12 09:47 | 只看该作者
本帖最后由 冷漠 于 2009-8-12 09:49 编辑

概念不对。你是要跳转到C主函数main:那个标号位置(地址)。编译器已在主函数main()中说明了  PUBLIC  main  所以主函数不用动了。

需要在另外文件(例如serial.src)中断汇编程序中加入“EXTRN  CODE(MAIN)”才能使连接程序找到主函数 main:的位置地址。

使用特权

评论回复
50
冷漠| | 2009-8-12 09:56 | 只看该作者
本帖最后由 冷漠 于 2009-8-12 10:01 编辑

?PR?main?TEST        SEGMENT CODE
?DT?TEST             SEGMENT DATA
        EXTRN        CODE (?C_STARTUP)
        PUBLIC        SP_BACK
        PUBLIC        main                        ;    C编译器自动做的。
        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:          ; 所以你只要在其他文件中配之以EXTRN CODE(main)就行了。
  ; {
  ?C0001:
;  // SP_BACK=SP;
; while(1)
   ; SOURCE LINE # 11
; {
   ; SOURCE LINE # 12
;        
;   _start: ......

使用特权

评论回复
51
冷漠| | 2009-8-12 10:07 | 只看该作者
回头参考31楼的例子:

第2个文件用汇编写的:comm.a51 (也是由comm.c改的。)

$NOMOD51
NAME        COMM

EXTRN  CODE(_start)    ;注意这2条添加的语句,把_start改为main即可。
EXTRN  DATA(SP_BACK)

使用特权

评论回复
52
xuzanlon| | 2009-8-12 15:25 | 只看该作者
好帖,但却发觉很多发言的同志根本没有看清题目就顶帖了……,楼主的这个问题很精辟,C讲究模块,函数有入必有出;而汇编却不一样,进入某个子程序后完全可以返回到一个毫不相干的地方。

使用特权

评论回复
53
xwj| | 2009-8-12 15:35 | 只看该作者
无语,这种“快速响应”纯粹是找死!

串口的速度才多快? 再“快速”又能快到多少???


老x现在就正在整改一个老的核心设备,之前的程序员(N年前的总工)就是喜欢这样子一个入口进然后到处散转,最后所有的人都不愿接手、修改他的程序,集体讨论后一致同意:全部推倒重新写。

使用特权

评论回复
54
程序匠人| | 2009-8-12 16:05 | 只看该作者
“冷漠”网友,ID叫“冷漠”,答复问题倒是很热心哦。奖励30分,见10楼,请笑纳。

使用特权

评论回复
55
czdo| | 2009-8-12 16:14 | 只看该作者
高手不少啊,可是我是新手没有什么好方法!

使用特权

评论回复
56
冷漠| | 2009-8-12 17:59 | 只看该作者
LZ的结构和53楼xwj说的不一样。LZ的结构并不是乱跳,他是跳到程序初始main,这是不是还可以视为有看门狗的作用。

谁都知道,看门狗被唤醒时产生的脉冲是使系统复位从头重新执行的。
那么LZ的结构可不可以视为:每接收一帧信息,接收中断程序都将系统复位从main重新开始执行。(main标号不在0000H,比看门狗恢复位置还好。)这相当于一次系统刷新,特别是当后台主程序死机了的时候,一个外部发送帧/本地接收中断就能把系统恢复到初始。一举两得。

当系统发生死机或死锁时,如果按照标准设计,中断返回到正常位置,岂不是恢复到死机位置维持了系统当机?

使用特权

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

本版积分规则