51单片机ucos ii任务切换汇编代码分析(1)

发布者:baiyuguoji最新更新时间:2020-04-29 来源: eefocus关键字:51单片机  ucos  任务切换  汇编代码 手机看文章 扫描二维码
随时随地手机看文章

ucos中任务切换函数都是汇编写的,属于“需移植”文件,


这个汇编文件名一般叫做:OS_CPU_A.ASM


要想看懂任务切换的原理,首先遇到的第一个难点,就是OS_CPU_A.ASM这个汇编文件里的一大堆不常见的汇编伪指令,搞懂这些指令是搞懂程序原理的第一步。


这篇文章先只分析这些汇编指令。


这个文件为ucos操作系统提供了4个API函数,分别是:


PUBLIC OSStartHighRdy;函数功能:切换到已就绪的任务横纵优先级最高的那个任务中去

PUBLIC OSCtxSw ;函数功能:一般的上下文切换,ContextSwitch,上下文切换又叫任务切换

PUBLIC OSIntCtxSw ;函数功能:在中断中进行上下文切换

PUBLIC OSTickISR ;函数功能:系统滴答


PULIC是汇编伪代码,表明所声明的函数可以被其他文件调用

首先来学习一个知识点,如何在汇编代码中写一个函数,才能使得这个函数能够被其他文件调用?不仅是加PUBLIC关键字这么简单,另外,我们还必须遵守一定的规范,可参考这篇文章,链接:点击打开链接


如果链接挂了,自行搜索关键字即可:《汇编函数与C函数的相互调用》


这个文件OS_CPU_A.ASM除了供外部文件引用自己的函数外,也需要引用别的文件的函数和变量,例如: 


EXTRN IDATA (OSRunning) ;声明引用IDATA 区的变量OSRunning

MOV  R0,#LOW (OSRunning) ;在汇编中使用外部变量

EXTRN CODE  (_?OSTaskSwHook) ;声明引用外部函数(代码),OSTaskSwHook()

LCALL _?OSTaskSwHook ;在汇编中调用C语言函数OSTaskSwHook()


解释:函数OSTaskSwHook是用C语言写的,名字为OSTaskSwHook,但是在汇编中引用它的话,必须在前面加前缀才行,由前面链接里的文章我们知道,如果我们在汇编中引用的是可重入函数,那么必须在函数名前面加_?前缀才能被汇编文件识别到。为什么要加前缀?因为C51的C语言函数转换为汇编的时候,keil编译器会自动把C语言的函数名给改掉,当然keil所做的改动是有规律的,例如,我们声明的可重入的C函数,keil转成汇编后,会自动在原先的函数名前加前缀“_?” 。


keil会自动添加什么前缀,添加的前缀有什么规范?这些问题可以参考keil的帮助文件,依次点击菜单栏->help->uVision help,在打开的帮助文件中搜索“Segment Naming Conventions(段命名惯例)”可查阅相关信息。


在汇编中写一个供C语言调用的函数的标准格式如下:


?PR?OSStartHighRdy?OS_CPU_A    SEGMENT CODE;先声明一个可重定位的代码段(这个语句的用法与解释可参考本博客的另一篇文章)

RSEG ?PR?OSStartHighRdy?OS_CPU_A;进行重定位,下面的代码都将被链接到在RSEG指令所指定的段中

OSStartHighRdy:      ;地址标号,作为函数名

·········;汇编函数的函数体,直到遇到CSEG/DSEG/RSEG 等段分配指令

上述代码解释:?PR?OSStartHighRdy?OS_CPU_A    SEGMENT CODE这一句不仅是声明了一个可重定位段的段名,这个段名的前缀为?PR?,这个前缀的意义是:该段是一个函数段(Executable program code)


再来看一个汇编调用C语言函数的例子:


在main.c文件中,我们定义了这样一个函数:



char add_two(char a1, char a2) REENTRANT

{

return a1+a2;

}

这个函数在keil编译之后如下:


85: char add_two(char a1, char a2) REENTRANT 

86: {        

C:0x269B    90FFFF   MOV      DPTR,#0xFFFF

C:0x269E    120436   LCALL    C?ADDXBP(C:0436)

C:0x26A1    ED       MOV      A,R5

C:0x26A2    F0       MOVX     @DPTR,A

C:0x26A3    90FFFF   MOV      DPTR,#0xFFFF

C:0x26A6    120436   LCALL    C?ADDXBP(C:0436)

C:0x26A9    EF       MOV      A,R7

C:0x26AA    F0       MOVX     @DPTR,A

    87:         return a1+a2; 

C:0x26AB    850883   MOV      DPH(0x83),?C_XBP(0x08)

C:0x26AE    850982   MOV      DPL(0x82),OutTxBuf(0x09)

C:0x26B1    A3       INC      DPTR

C:0x26B2    E0       MOVX     A,@DPTR

C:0x26B3    FF       MOV      R7,A

C:0x26B4    850883   MOV      DPH(0x83),?C_XBP(0x08)

C:0x26B7    850982   MOV      DPL(0x82),OutTxBuf(0x09)

C:0x26BA    E0       MOVX     A,@DPTR

C:0x26BB    2F       ADD      A,R7

C:0x26BC    FF       MOV      R7,A

88: } 

C:0x26BD    900002   MOV      DPTR,#0x0002

C:0x26C0    020436   LJMP     C?ADDXBP(C:0436)


由汇编代码我们可以看到,该函数被放在了0x269B地址处,继续观察keil生成的.m51文件(即map文件),搜索add_two,发现相关内容如下:

(1)CODE    269BH     0028H     UNIT         ?PR?_?ADD_TWO?MAIN


(2)C:269BH         PUBLIC        _?add_two

(3)-------         PROC          _?ADD_TWO

  x:0000H         SYMBOL        a1

  x:0001H         SYMBOL        a2

  C:269BH         LINE#         85

  C:26ABH         LINE#         87

  C:26BDH         LINE#         88

-------         ENDPROC       _?ADD_TWO


有上述查到的内容发现,keil在编译add_two()函数的过程中,做了3个工作:


(1)为add_two()函数声明了一个段,位置从269BH开始,大小为0028H ,这个段中只含有add_two这个函数的代码段,不含其他函数,也不不含任何数据段,段名为:?PR?_?ADD_TWO?MAIN(段名由3部分组成:一是固定前缀?PR?,二是函数名的大写ADD_TWO,并且keil在为函数生成汇编时,自动为可重入函数的函数名前加前缀_?,三是模块名,默认的模块名即该函数所在的文件名)。


(2)keil对“为add_two()生成的汇编函数”进行了PUBLIC声明,以供其他文件调用该函数,但是声明函数名的时候,加了_?前缀:_?add_two,如果有汇编文件打算调用add_two()函数,就得这样:


EXTRN CODE  (_?add_two) ;声明引用外部函数(代码):add_two()

LCALL _?add_two ;在汇编中调用C语言函数add_two()

按照keil的命名惯例,


_?前缀的函数是可重入函数。


拓展资料:其他类型的函数的命名惯例如下:


无参函数: ?PR?函数名?文件名

有参函数: ?PR?_函数名?文件名

可重入函数: ?PR?_?函数名?文件名


(3)这是add_two()函数的符号表,也就是指出了add_two()函数中的形参和局部变量所在的存储位置。那么这里有个疑问,为什么a1、a2被放在了00h和01H地址处呢,这两个地址不是寄存器R0和R1吗?这就涉及到了keil的编译规则,形参的类型、数量不同时,传参的方法都是不一样的,形参往哪里放有专门的文章介绍,一般来说,形参和局部变量较少时,全部都用寄存器Rn来传递和存储;数量较多时,不可重入函数的形参和局部变量在Rn不够用时,其余的存放到固定的内存地址中,可重入函数的形参和局部变量在Rn不够用时,其余的入仿真栈。

关键字:51单片机  ucos  任务切换  汇编代码 引用地址:51单片机ucos ii任务切换汇编代码分析(1)

上一篇:51单片机之IO口扩展
下一篇:基于51单片机的贪吃蛇游戏

推荐阅读最新更新时间:2024-10-30 10:05

51单片机 外部中断实验
51单片机一共有两个外部中断源。 IE0的置位与否与IT0有关,当IT0=1时,下降沿触发也就是说当INT0由高到低时IE0将被硬件置1, 执行完中断,遇到RETI自动清0,但不影响INT0的状态。当IT0=0时,当CPU检测到连续两个周期的INT0低电平时IE0置1, 中断结束时遇到RETI自动将IE0清0,之后如果INT0仍然为低电平,且长度超过两个机器周期, 那么将重新将IE0置1申请中断。 /** * 文件名称:外部中断实验 * 实验目的:1.掌握51单片机外部中断相关寄存器的配置方法和触发方式 * 程序说明:1.使用程序前,将跳线J2调整为BTN模式(独立按键) * 将跳线J13调整为IO模式
[单片机]
基于51单片机的定时器
在这里,小编带你一起 从零开始学51 单片机 定时器。基于单片机的定时器 电路 原理图如下所示:   我们学单片机是首先学的就是 LED 闪烁,那是用延时程序做的,现在回想起来,这样做不很恰当,为什么呢?我们的主程序做了灯的闪烁,就不能再干其它的事了,难道单片机只能这样工作吗?当然不是,我们能用定时器来实现灯的闪烁的功能。   例 1:查询方式   ORG 0000H   AJMP START   ORG 30H   START:   MOV P1,#0FFH ;关所 灯   MOV TMOD,#00000001B ;定时/计数器 0 工作于方式 1   MOV TH0,#15H  
[单片机]
基于<font color='red'>51单片机</font>的定时器
51单片机向PC电脑发送汉字的方法
简介:最近看到有朋友在网上问单片机怎么向电脑发送一串汉字这个问题,其实这个问题也不难.呵呵.只要把相关的参数设置好一些,然后把汉字定义成一组字符向电脑发送就可以. 为了让大家更明确的了解,我就写了下面的一个程序来演示一下. 操作条件: 1.XP操作系统. 2.XP的超级终端显示. 3.WJ-V4.0开发板. 4.单片机STC89C52. 5.晶振11.0592M 操作步骤: 1.设置TMOD设置波特率和定时器1的工作方式. 2.设置定时器的初始值. 3.设置串行口工作方式. 4.设置波特率不加倍. 5.打开TR1允许发送. 6.启动定时器. 7.串行中断打开. 8.打开E
[单片机]
<font color='red'>51单片机</font>向PC电脑发送汉字的方法
51单片机执行指令的过程
51单片机执行指令的过程 单片机执行程序的过程,实际上就是执行我们所编制程序的过程。即逐条指令的过程。计算机每执行一条指令都可分为三个阶段进行。即取指令-----分析指令-----执行指令。 取指令的任务是:根据程序计数器PC中的值从程序存储器读出现行指令,送到指令寄存器。 分析指令阶段的任务是:将指令寄存器中的指令操作码取出后进行译码,分析其指令性质。如指令要求操作数,则寻找操作数地址。 计算机执行程序的过程实际上就是逐条指令地重复上述操作过程,直至遇到停机指令可循环等待指令。 一般计算机进行工作时,首先要通过外部设备把程序和数据通过输入接口电路和数据总线送入到存储器,然后逐条取出执行。但单片机中的程序一般事先我们都已通过写入器
[单片机]
图形点阵式液晶显示模块与51单片机的接口设计与应用
引 言 液晶作为一种显示器件,以其特有的优势正广泛应用于仪器、仪表、电子设备等低功耗产品中。以往的测控仪器的显示部分大都采用LED式液晶显示屏进行参数设定和结果显示,其显示信息量少、形式单一、人机交互性差、操作人员要求较高。而液晶显示器(LCD)具有功耗低、体积小、质量轻、超薄和可编程驱动等其他显示方式无法比拟的优点,不仅可以显示数字、字符,还可以显示各种图形、曲线、及汉字,并且可实现屏幕上下左右滚动、动画、闪烁、文本特征显示等功能;人机界面更加友好,使用操作也更加灵活、方便,使其日益成为智能仪器仪表和测试设备的首选显示器件。本文在介绍以ST7920为驱动器的WGM-12832液晶显示模块的引脚、结构、功能的基础上,详述了与AT
[单片机]
图形点阵式液晶显示模块与<font color='red'>51单片机</font>的接口设计与应用
51单片机实验3:led流水灯
开发板led模块电路图如下: 循环左/右移函数头文件为 intrins.h #include reg52.h #include intrins.h #define uc unsigned char void delay(uc n) { uc i,j; for(i=1;i =n;i++) for(j=110;j =1;j--); } void main() { P2=0xFE; while(1) { delay(200); p2=_crol_(P2,1); delay(200); } }
[单片机]
<font color='red'>51单片机</font>实验3:led流水灯
51单片机与RS485应用电路图
最近用到RS485,找了点资料,保存保存以后用。 --------以上部分请勿修改!------------- 提高485总线的可靠性 摘 要:就485总线应用中易出现的问题,分析了产生的原因并给出解决问题的软硬件方案 和措施。 关键词:RS-485总线、串行异步通信 -------------------------------------------------------------------------------- 1 问题的提出 在应用系统中,RS-485半双工异步通信总线是被各个研发机构广泛使用的数据通信总 线,它往往应用在集中控制枢纽与分散控制单元之间。系统简图如图1所示。 图1. R
[单片机]
<font color='red'>51单片机</font>与RS485应用电路图
风河为Altera Nios II嵌入式提供Linux支持
      Altera公司和Wind River公司宣布为Altera Nios® II嵌入式处理器提供Linux支持。嵌入式开发人员实现基于Nios II处理器的产品时可以在Altera全系列FPGA和HardCopy® ASIC上使用这一Linux解决方案。   Wind River公司的Nios II处理器Linux解决方案基于Linux 2.6内核技术、GNU 4工具链和Eclipse Wind River工作台开发包。该方案依据业界著名的Linux标准和工具,定制支持Nios II指令集,处理器体系结构和定制指令可以在FPGA架构中实现,从而提高了系统性能。   Wind River公司网络解决方案总经理Mik
[嵌入式]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved