关于C51中__nop__()函数的一点疑惑

wenjiu5 2017-11-28 10:54:06
背景:
__nop__函数对应汇编语言中的nop指令,在intrins.h中找到了__nop__()函数的原型如下:
extern void _nop_ (void);
从C语言的角度这是一个外部函数,这样一来调用__nop__函数的时候应该生成一条LCALL指令。但事实上却不是这样,看了编译生成的lst文件,__nop__()调用仅仅被编译成了一条nop指令,也就是说编译器并没有把__nop__当成一个函数来处理。

疑惑:
从__nop__函数的原型声明来看,其就是一个外部函数,并没有特殊的关键字或编译选择指明这是一个“特殊”的“函数”,那编译器是如何知道这不是一个普通的函数而不生成LCALL指令呢?换句话说,如果我自己写定义一个这样“特殊”的“函数”应该怎么做呢?
...全文
1165 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
坤小白 2019-05-21
  • 打赏
  • 举报
回复
编译器直接就给优化了
qq_34007813 2019-05-20
  • 打赏
  • 举报
回复
引用 12 楼 qq_34007813 的回复:
[quote=引用 10 楼 wenjunlin2000 的回复:]
[quote=引用 9 楼 qq_34007813 的回复:]
补充,请参照C99内联函数


问题在于C51没有遵守C99,否则也就没必要讨论这个话题了。[/quote]
这个问题你可以去微软的这个网站得到答案,https://docs.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics?view=vs-2019
还有这个https://docs.microsoft.com/zh-cn/previous-versions/f99tchzc(v=vs.120)
他们都是一个道理。[/quote]
还有一个,微软的Visual Studio 有一个编译参数 /Oi可以生成这类内部函数,再者可用#pragma function(你的函数名)这种编译器指令来生成,还可以加上"FORCEINLINE"来生成。而Keil C51完全没有开放这样的指令或开关(好像Keil ARM 可以在函数前加inline),所以楼主想实现这类函数还得改编译器逻辑。
qq_34007813 2019-05-20
  • 打赏
  • 举报
回复
引用 10 楼 wenjunlin2000 的回复:
[quote=引用 9 楼 qq_34007813 的回复:]
补充,请参照C99内联函数


问题在于C51没有遵守C99,否则也就没必要讨论这个话题了。[/quote]
这个问题你可以去微软的这个网站得到答案,https://docs.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics?view=vs-2019
还有这个https://docs.microsoft.com/zh-cn/previous-versions/f99tchzc(v=vs.120)
他们都是一个道理。
fly 100% 2019-04-09
  • 打赏
  • 举报
回复
编译器已经定义的这个函数,你只是实现它 适配不同的芯片
wenjiu5 2019-04-08
  • 打赏
  • 举报
回复
引用 9 楼 qq_34007813 的回复:
补充,请参照C99内联函数
问题在于C51没有遵守C99,否则也就没必要讨论这个话题了。
qq_34007813 2018-04-05
  • 打赏
  • 举报
回复
补充,请参照C99内联函数
qq_34007813 2018-01-08
  • 打赏
  • 举报
回复
个人最近也对这个问题感兴趣,我是这么想的。intrins这个库里的函数它不生成LCALL指令是因为这些函数从来就没有存在过,它是函数就必定生成LCALL,个人感觉它就类似于宏替换。我们知道子函数的地址都是独立于主函数之外的,而当调用了_nop_()时,并未转向函数调用,而是直接在CALLER里生成一条汇编指令,地址也重定位到CALLER的范围内,推测他用了某些特殊编译参数,替换了_nop_()(可见_nop_()只是一个符号)。但说实话个人感觉写这种函数意义不大,除非你需要精确到指令周期,所以他也不开放给我们用了吧?
w22net 2017-12-04
  • 打赏
  • 举报
回复
因为这个函数名字特殊
ckc 2017-11-29
  • 打赏
  • 举报
回复
可能是个宏定义,这样就没有调用的开销了
大米粥哥哥 2017-11-29
  • 打赏
  • 举报
回复
引用 4 楼 wenjunlin2000的回复:
[quote=引用 2 楼 qq_38204686 的回复:] 现在的编译器很强大的 会优化 你可以直接上汇编
51的编译器还没有强大到那种程度,你自己写个函数里边只写一条nop汇编指令,编译器还是会把这个函数当成普通函数编译,不会只当成一条指令。[/quote] 那我很好奇 不是编译器干的谁干的
wenjiu5 2017-11-29
  • 打赏
  • 举报
回复
引用 3 楼 ckc 的回复:
可能是个宏定义,这样就没有调用的开销了
如果是个宏定义,那一定能在编译器提供的头文件里看到这个宏的定义,否则在预处里时没法做宏展开。可实际上编译器的头文件里没有这个宏。
wenjiu5 2017-11-29
  • 打赏
  • 举报
回复
引用 2 楼 qq_38204686 的回复:
现在的编译器很强大的 会优化 你可以直接上汇编
51的编译器还没有强大到那种程度,你自己写个函数里边只写一条nop汇编指令,编译器还是会把这个函数当成普通函数编译,不会只当成一条指令。
大米粥哥哥 2017-11-28
  • 打赏
  • 举报
回复
现在的编译器很强大的 会优化 你可以直接上汇编
dceacho 2017-11-28
  • 打赏
  • 举报
回复
因为编译器不笨啊 编译器一看,我草,你这函数就一个指令,我进栈出栈都2个了,调个毛线,直接替换了
引用
如果我自己写定义一个这样“特殊”的“函数”应该怎么做呢?
函数里的NOP多几个,优化关掉试试, 这个问题没仔细研究过,一般控制时序时都是随便放几个然后逻辑分析仪直接看准确延时

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧