配色: 字号:
单片机._C与汇编混合编程
2019-12-25 | 阅:  转:  |  分享 
  
C和ASM的混合编程jianghq2003-5TsinghuaDEEContent程序的结构汇编程序C程序project
框架如何改写汇编程序?在C程序中如何做一些底层操作?程序的结构存储空间结构M30624FGFPMemoryM
ap几个主要的参数RAM区ramTOP ramENDROM区progTOPVvec
tor汇编程序结构-段类型 RAM->DATA ROM->
CODE ROMDATA汇编程序结构-段定义汇编程序中几个主要的参数VramTOP .EQU
000400HVramEND .EQU 002BFFHVIstack .EQU 002C00H-》ISP
VprogTOP .EQU 0F0000H Vintbase .EQU 0FA000HVvector .EQU 0FF
FDCHSB_base .EQU 000380H-》SB关于SB和FB关于堆栈两种堆栈:堆栈
指针ISP和USP使用何种堆栈,由堆栈指针选择标志位(U标志)选取。 U=0选取中断堆栈指针ISPU=1
选取用户堆栈指针USP响应中断后,该标志清0,执行中断子程序SP指针位置如何设定:栈顶指针 Push:S
P=SP–1 Pop:SP=SP+1C程序结构RAM->DATA
->data bss stack
heapROM->CODE->program
ROMDATA->rom vector
fvectorNC编译器对Section的处理Section的属性C程序中所有的section列表
根据芯片修改sect30.inc注释掉不存在的段最重要的三个段的位置设定 .section data_SE,DATA .
org 400H .section rom_FE,ROMDATA .org 0C0000H .section vec
tor,ROMDATA .org VECTOR_ADR VECTOR_ADR .equ 0FA000H其他的段就交给编译
器来处理 例子:一个Section分配的结果C程序结构-project可能包括多个asm文件,C文件如何安排pr
oject的结构?程序的入口首先要清楚整个程序的执行过程从哪里开始执行?Startup文件sect30.inc
文件Startup文件ncrt0.a30文件启动过程 ncrt0.a30设定单片机工作模式RAM清0变量初值
设定堆初始化调用全局Init子程序调用全局Main子程序exit循环Project层次框架一个project的层次图
程序结构小结明白各个Section的含义根据芯片参数和自己的程序需要来修改startup程序用层次化来保持整个组织结构的
清晰如何改写汇编程序?目标: 将他人提供的汇编程序转为可供自己在C程序中调用的子函数。例子
: 红外接收的子程序Step1大致看懂原程序完成了一个什么样的功能。 主要的几个变量是什么含义。Step2分
析自己的要求如果将该汇编程序独立出来作为一个子函数;那么其功能是什么?输入参数:有哪些返回值:有哪些我希望实现的功能
等待接收一个字节,如果收到立刻返回该字节,没收到且时间超过300ms,那么也返回,同时指示状态为未接收。charrec
v_status=IR_RECV(charuserID,charpByte);指示接收状态
接收用户码接收字节地址Step3对原来的程序进行裁减删去原有的各个段定义重新定
义各个Section:bss_SE,rom_FE,program定义和声明全局子函数_IRR_INIT_IR
_RECVI_timera0 涉及C和汇编子程序之间的参数传递(详见下文)删除不必要的变量和程序如果使用中断,则将中断向量
表设置挪至sect30.inc最后以.end结束文件C和汇编子程序之间的参数传递参数规则(从C到汇编)参数规则(从汇编返回
到C)函数名定义规则参数规则(从C到汇编)参数规则(从汇编到C)函数名定义规则最后结果C程序部分:externch
arIR_RECV(char,char);#pragmaPARAMETERIR_RECV(R0L,A0)汇编语言部
分: .glb_IR_RECV ;全局调用声明_IR_RECV: mov.bR0L,N_CSTM ;参
数传递:用户码 mov.wA0,SAVE_ADDR ;参数传递:接收结果地址………… mo
v.b#1,R0L ;返回1,如果收到了数据改写汇编程序小结看懂源程序在明白自己所需要的功能后,再
进行修改有的时候还是需要改多一些地方。该例子存放到ftp://166.111.172.7在C程序中如何做一些底层操作特
殊寄存器的操作BIT操作特殊寄存器的操作方法1:使用#pragmaADDRESS #pragmaADDRESS
TA0 0386H#pragmaADDRESSTABSR 0380H……建议将所有SFR地址声明放
在一个文件里#include“mcu16c62.h”定义类型(根据其所占的内存大小)charTA0MR,TA0IC
,TABSR;unsignedintTA0;特殊寄存器的操作方法2:嵌入汇编语句asm() 尤其是一些系统寄存器R0,
FLG 方法3:定义成汇编子函数 另写一个as30文件,将相关的操作封装成函数,供C程序调用 方法4:直接定义指针,并
对该指针赋初值 BIT操作使用位域BIT操作使用宏#defineSET_BIT(n,byteA){byte
A|=(0x01<{byteA&=(~(0x01<n,byteA)(byteA&(0x01<完了,还要考虑哪些问题? A.是否用了动态分配内存的函数->HEAPSIZE malloc,allot,...
.. 如果用了,则Heapsize够不够。 没用,。。。注释掉,节约资源。 B.堆栈的大小够否? -
>STACKSIZE,ISTACKSIZE 可直接用StackCalulate(TM工具栏上)查看这两个参数
的设定都在ncrt0.a30中《单片机与嵌入式系统》汇编程序结构C程序结构 .SECTION memory,DATA
;数据段 .ORG VramTOP .SECTION prog,CODE ;代码段 .ORG Vpro
gTOP .SECTION val_vect,ROMDATA;用户自定义中断向量段 .ORG Vintbase
.SECTION inter,ROMDATA;固定中断向量段 .ORG Vvector+(84) .SB SB_
base .SBSYMrecv_nums 告诉编译器使用该变量的指令寻址方式采用相对基址寻址方式
,可以提高生成代码的效率。属性:I(是否初值),N/F(扩展区)S(SB寻址区),E/O(偶地址对齐)举例:bss_SE
,bss_NE,data_FE,data_SEI data_SE bss_SE data_SO bss_SO
data_NE bss_NE data_NO bss_NO stack heap data_FE bss_FE
data_FO data_FE DATA rom_NE rom_NO rom_FE rom_FO data_S
EI data_SOI data_NEI data_NOI data_FEI data_FOI vector
fvectorROMDATACODE program interrupt program_S;fixedvecto
rsection .org 0fffdch…………NMI: .lword dummy_intRESET: .lwo
rd start.end .glb start .section interruptstart:;---------
------------------------------------------------------------;af
terreset,thisprogramwillstart;------------------------------
--------------------------------------- ldc #istack_top, isp ;se
tistackpointer 主C程序VoidInit(){ ……}VoidMain(){}
主C文件:init(){int1();int2();int3();……}main(){sub1();sub4();……}Startup文件:ncrt0.a30系统提供的库程序:#include“stdlib.h”ASM子程序:init1();sub1()C子程序1:init2();sub2();sub3()C子程序2:init3();sub4();ASM子程序:init4();sub5()采用#pragmaPARAMETER
献花(0)
+1
(本文系璞子的家首藏)