




已阅读5页,还剩17页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Keil软件“C语言”与“汇编”混编相关知识整理用Keil在C中嵌入汇编1在Keil中嵌入汇编2介绍直接嵌入汇编代码的方法4采用汇编可能会有的好处5Keil C语言与汇编语言混合编程7深入剖析Keil C51 从汇编到C519C语言和汇编语言的变量以及函数的接口问题14汇编与C语言混合编程的关键问题15KEIL段重定位16用Keil在C中嵌入汇编 早前公布了C和汇编混编的温度控制器程序,收到一些朋友的询问,他们无法在自己程序中使用我的18B20的汇编子程序或无法正常通过混编后的程序编译。 其实在KEIL中嵌入汇编的方法很简单。如图一,在C文件中要嵌入汇编的地方用#pragma asm和#pragma endasm分隔开来,这样编译时KEIL就知道这中间的一段是汇编了。 图1 在有加入汇编的文件中,还要设置编译该文件时的选项图2 Generate Assembler SRC File 生成汇编SRC文件 Assemble SRC File 封装汇编文件 (如图三的状态为选中) 选上这两项就可以在C中嵌人汇编了,设置后在文件图示中多了三个红色的小方块。图3 为了能对汇编进行封装还要在项目中加入相应的封装库文件, 在笔者的项目中编译模式是小模式所以选用C51S.LIB。这也是最常用的。这些库文件是中KEIL安装目录下的LIB目录中。 加好后就可以顺利编译了。(注:我只在7.0以上版本使用过)图4在Keil中嵌入汇编 1、其实在KEIL中嵌入汇编的方法很简单。如图1,在C文件中要嵌入汇编的地方用#pragma asm和#pragma endasm分隔开来,这样编译时KEIL就知道这中间的一段是汇编了。 2、在有加入汇编的文件中,还要设置编译该文件时的选项,如图2所示。 3、Generate Assembler SRC File 生成汇编SRC文件 Assemble SRC File 封装汇编文件 (如图3的状态为选中) 选上这两项就可以在C中嵌人汇编了,设置后在文件图示中多了三个红色的小方块。 4、为了能对汇编进行封装还要在项目中加入相应的封装库文件, 在笔者的项目中编译模式是小模式所以选用C51S.LIB。这也是最常用的。这些库文件是中KEIL安装目录下的LIB目录中。 加好后就可以顺利编译了介绍直接嵌入汇编代码的方法1、在 C 文件中要嵌入汇编代码片以如下方式加入汇编代码: #pragma ASM ; Assembler Code Here #pragma ENDASM2、在 Project 窗口中包含汇编代码的 C 文件上右键,选择“Options for .”,点击右边的“Generate Assembler SRC File”和“Assemble SRC File”,使检查框由灰色变成黑色(有效)状态;3、根据选择的编译模式,把相应的库文件(如 Small 模式时,是 KeilC51LibC51S.Lib)加入工程中, 该文件必须作为工程的最后文件;采用汇编可能会有的好处C51编译器能对C语言程序进行高效率的编译,生成高效简洁的代码,在大多数的应用场合,采用C语言编程即可完成预期的任务,但是,在有些场合还是会用到汇编,例如在下面的几种情况下,采用汇编可能会有很多好处:电子园51单片机学习网|;eWuE1、已有程序的移植:在单片机领域工作很久的工程人员可能会保留有很多的早期用汇编语言编制的程序模块,并且这些模块已经经过实际应用的验证,如果重新用C编程,可能工作量很大,这时就可以用嵌入汇编的方式把以前的汇编模块植入新的应用,可以明显的加快开发的进度。5WhX)Ouq3g446062、局部功能需要足够短的执行时间:在有些应用中,部分的功能模块需要有很高的执行效率,而有些汇编的指令在C中没有对应的指令,这给我们对单片机的高效操作带来困难,嵌入汇编可是我们的程序执行更有效率。&K0u.g.S(Q446063、对一些特定地址进行操作:在C中我们要对特定地址进行读写,一般用以下两种方式:用_AT_指令定义变量;定义指向外部端口或数据地址的指针;在汇编中只需要使用MOVX A,DPTR或MOVX DPTR,A就可以了,这样可以增强程序的可读性。?&B&oYD)x6xx&x446064、其他的需要汇编的应用:在这里我们不可能举出所有可能要用汇编的例子,在你的应用中,你可能在一个或多个应用中感到C语言的不足,而需要用到汇编指令,请你记住,可以在C中嵌入汇编子程序,这对你的程序非常有用。9h3;oVO$F$QUN6)s44606 首先介绍一下调用汇编的参数传递规则,见下表3KSpXPdi2Io+h Vu44606 传递的参数char、1字节指针int、2字节指针long、float一般指针第一个参数R7R6,R7R4R7R1,R2,R3第二个参数R5R4,R5 R1,R2,R3第三个参数R3R2,R3无R1,R2,R3在下面的例子中我们首先给出一个C程序调用汇编的例子,先说明一下,在这个例子中,你完全可以用C完成,我用这个例子,只是为了说明嵌入汇编的方法。电子园51单片机学习网qb7h3V例1:电子园51单片机学习网juO2z C下面是C语言的主程序#include #include extern char asm(char c,char b);bit VAL;void main (void) char out=0x49; Char direct; Char key; SCON = 0x50;/* SCON: mode 1, 8-bit UART, enable rcvr */ /10位异步接收器,可变。REN=1,允许接收数据 TMOD |= 0x20;/* TMOD: timer 1, mode 2, 8-bit reload */ /定时器1工作于模式2 TH1 = 0xfd;/* TH1: reload value for 9600 baud 11.0592MHz */ TR1 = 1;/* TR1: timer 1 run */ TI = 1;/* TI: set TI to send first char of UART */ VAL = 0; while (1) key=getchar(); if(key=R) direct=0X01; out=asm(out,direct);/*汇编子程序调用*/ printf (Right rotaten); if(key=L) direct=0X02; out=asm(out,direct);/*汇编子程序调用*/ printf (Left rotaten); printf(%bxn,out); 下面是汇编的子程序(文件名称asmtest.asm)NAME ASM?PR?_asm?ASMTEST SEGMENT CODE?BI?_asm?ASMTEST SEGMENT BITPUBLIC ?_asm? BITPUBLIC _asmRSEG ?BI?_asm?ASMTEST?_asm?BIT:VAL:DBIT 1RSEG ?PR?_asm?ASMTEST_asm:MOV A,R7MOV C,VALDJNZ R5,JP1RRC AJP1:DJNZ R5,JP2RLC AJP2:MOV 90h,AMOV R7,AMOV VAL,CRETEND现在对这个例子简短的说明,这个例子是用来驱动一个不带细分的三相步进电机,用的是循环移位的指令来实现的,由于一个字节是8位,如果算上进位位,共9位,通过付值,可以得到这样的数100100100,大家可以看到任意取中间的3位,相邻的每3位与它都一样,这样我们就可以去中间的3位输出到端口去驱动一个三相的步进电机,通过对这个9位的二进制数进行循环移位,可以实现电机的步进,在51系列单片机中有两条指令可以帮助我们进行循环移位操作,这就是RRC A和RLC A指令,我们只要把第九位保存好,在需要移位操作时,把它付给PSW中C,再执行循环移位就可以了。在这个例子中,我发现了几个需要注意的地方:1、在C程序中,我不能把VAL变量设为extern类型,否则在连接时会有警告,导致数值不能传递;电子园51单片机学习网 _t)a|2、在汇编模块中,不能把SEGMENT BIT段置为OVERLAYABLE即可覆盖段,如果置为可覆盖段,那么在进入汇编模块时VAL变量值丢失;电子园51单片机学习网3DE z%Au,W3、如果把VAL变量作为函数的参数传递,出现在返回后在执行printf函数后变量值丢失;上面是本人写的一个C程序调用汇编的小例子,在本例中的几个printf函数是为了便于在Keil C51中模拟调试时观察运行结果的,在实际应用中可以将这几条去掉,这只是一个简短的示例,目的在于介绍一下C调用汇编的用法,希望对大家有帮助,同时由于本人水平有限,在程序中有些地方可能仍有不周到之处,欢迎广大单片机高手不吝指出。Keil C语言与汇编语言混合编程C51和汇编混合编程(1)C语言中嵌入汇编1、在 C 文件中要嵌入汇编代码片以如下方式加入汇编代码: #pragma ASM ;Assembler Code Here #pragma ENDASM2、在 Project 窗口中包含汇编代码的 C 文件上右键,选择“Options for .”,点击右边的“Generate Assembler SRC File”和“Assemble SRC File”,使检查框由灰色变成黑色(有效)状态;3、根据选择的编译模式,把相应的库文件(如 Small 模式时,是 KeilC51LibC51S.Lib)加入工程中, 该文件必须作为工程的最后文件;4、这点也是本人要重要说明的!即一定要将c:keilC51下的STARTUP.A51文件加入项目5、编译,即可生成目标代码。来个实例吧:#include void main(void) P2=1; #pragma asm MOV R7,#10 DEL: MOV R6,#20 DJNZ R6,$ DJNZ R7,DEL #pragma endasm P2=0;C51和汇编混合编程(2)无参数传递的函数调用先来个例子:其中example.c和example.a51为项目中的两个文件*example.c*extern void delay100();main()delay100;*example.a51*?PR?DELAY100 SEGMENT CODE; / 在程序存储区中定义段PUBLIC DELAY100; / 声明函数RSEG ?PR?DELAY100; / 函数可被连接器放置在任何地方DELAY100: MOV R7,#10DEL: MOV R6,#20 DJNZ R6,$ DJNZ R7,DEL RETEND在example.c文件中:先声明外部函数,然后直接在main中调用即可。在example.a51中:?PR?DELAY100 SEGMENT CODE; 作用是在程序存储区中定义段,DELAY100为段名,?PR?表示段位于程序存储区内PUBLIC DELAY100; 作用是声明函数为公共函数RSEG ?PR?DELAY100; 表示函数可被连接器放置在任何地方,RSEG是段名的属性,段名的开头为PR,是为了和C51内部命名转换兼容段名命名转换规律如下:CODE ?PR?XDATA ?XDDATA ?DTBIT ?BIPDATA ?PDC51和汇编混合编程(3)有参数传递的函数调用 在写这片文章之前,写了个试验程序,但总是通不过,查看汇编代码发现c文件中的语句根本没有被编译进去,怎么也找不到原因,郁闷 最后在网上搜了个试验程序,把我的程序复制过去,可以编译成功,奇怪了,在我的project里就是不行,我注意到我的project编译后出现一条WARNING:* WARNING L7: MODULE NAME NOT UNIQUE MODULE: 8.obj (8) 而同样的程序代码在另外一个project中没有WARNING,肯定是这条WARNING语句导致的,里面提到NAME,难道和名字有关,马上把A51文件改个名字(原来c文件和a51文件名字一样),编译,哈哈,WARNING不见了,查看汇编代码,一切按预想的进行,唉,一个名字害得我不浅啊,记住哦,c文件和A51文件不能使用同一个文件名,不过我还不知道为什么会这样,有高手知道得话请告知,还是进行今天的作业吧! 今天说说带参数传递的函数调用,在C51和汇编之间传递参数的方式有两种,一种是通过寄存器传递参数,C51中不同类型的实参会存入相应的寄存器,在汇编中只需对相应寄存器进行操作,即达到传递参数的目的。不同类型的数据及其传递参数的寄存器如下表所示:参数类型charintlong/float通用指针第1个R7R6&R7R4-R7R1-R3第2个R5R4&R5R4-R7R1-R3第3个R3R2&R3-R1-R3 举个例子吧,void delay(unsigned char i, unsigned int j) 当执行语句delay(10,1000)时,10会存入R7中,1000高位会存入R4中,低位存入R5中。在汇编语句中从这几个寄存器中取数,再进行操作就行了,说起来也很简单的嘛,呵呵 来个最简单的实例吧,没什么意义,傻瓜式的程序:*main.c*extern void DELAY(unsigned char i,unsigned int j);main() DELAY(10,1000); while(1);*DELAY.A51*?PR?_DELAY?DELAY SEGMENT CODE PUBLIC _DELAYRSEG ?PR?_DELAY?DELAY_DELAY: DJNZ R4,$ DJNZ R5,$ DJNZ R7,$ RET END 还要说的是,函数名前要加下划线,表示是有参数传递的函数调用!C51和汇编混合编程(4)函数的返回值传递参数函数返回值所用的寄存器 返回值类型寄存器说明BitC由具体标志位返回char/unsigned char / 1 byte 指针R7 int/unsigned int / 2 byte 指针R6&R7高位在R6long/unsigned long / 3 byte 指针R4-R7高位在R4floatR4-R732bit IEEE格式,指数和符号位在R7通用指针R1-R3存储类型在R3,高位在R2实例:*main.c*unsigned int example(unsigned char i) return(i*i);main() example(80); #pragma asm DJNZ R7,$ DJNZ R6,$ #pragma endasm while(1);函数返回值在R6,R7中。深入剖析Keil C51 从汇编到C51/*/ 内容一:main()函数和启动代码/*/汇编是从org 0000h开始启动,那么keil c51是如何启动main()函数的?keil c51有一个启动程序startup.a51,它总是和c程序一起编译和链接。下面看看它和main()函数是如何编译的;主函数如下;void main(void) /这是个无条件空循环。 while(1) / 把上面的main()函数编译后的汇编程序和反汇编代码整理后对照如下;;* From STARTUP.A51 *$NOMOD51IDATALEN EQU 80HXDATASTART EQU 0 XDATALEN EQU 0 PDATASTART EQU 0HPDATALEN EQU 0HIBPSTACK EQU 0 ; set to 1 if small reentrant is used.IBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1 XBPSTACK EQU 0 ; set to 1 if large reentrant is used.XBPSTACKTOP EQU 0xFFFF +1 ; default 0FFFFH+1 PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.PBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1 PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.PPAGE EQU 0PPAGE_SFR DATA 0A0H;-; Standard SFR Symbols ACC DATA 0E0HB DATA 0F0HSP DATA 81HDPL DATA 82HDPH DATA 83H NAME ?C_STARTUP?C_C51STARTUP SEGMENT CODE;在实际操作中未找到原文中的下1行信息;?PR?main?TESTMAIN SEGMENT CODE?STACK SEGMENT IDATA RSEG ?STACK DS 1 EXTRN CODE (?C_START) PUBLIC ?C_STARTUP CSEG AT 0?C_STARTUP: LJMP STARTUP1 RSEG ?C_C51STARTUPSTARTUP1: ;该段程序把内存清零; 0 条件判断,不等于0的意思。IF IDATALEN 0 MOV R0,#IDATALEN - 1 CLR AIDATALOOP: MOV R0,A DJNZ R0,IDATALOOPENDIF;* From Disassemble * 126: ?C_STARTUP: LJMP STARTUP1 127: 128: RSEG ?C_C51STARTUP 129: 130: STARTUP1: ;该段程序把内存清零 131: 132: IF IDATALEN 0 C:0x0000 020003 LJMP STARTUP1(C:0003) 133: MOV R0,#IDATALEN - 1 C:0x0003 787F MOV R0,#0x7F 134: CLR A C:0x0005 E4 CLR A 135: IDATALOOP: MOV R0,A C:0x0006 F6 MOV R0,A 136: DJNZ R0,IDATALOOP C:0x0007 D8FD DJNZ R0,IDATALOOP(C:0006) 185: MOV SP,#?STACK-1 ;设制CPU的堆栈起始地址 186: 187: ; This code is required if you use L51_BANK.A51 with Banking Mode 4 188: ; Code Banking 189: ; Select Bank 0 for L51_BANK.A51 Mode 4 190: #if 0 191: ; Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4. 192: EXTRN CODE (?B_SWITCH0) 193: CALL ?B_SWITCH0 ; init bank mechanism to code bank 0 194: #endif 195: ; C:0x0009 758107 MOV SP(0x81),#0x07 196: LJMP ?C_START C:0x000C 02000F LJMP main(C:000F) 2: ;在实际操作中未找到原文中的下3行信息; RSEG ?PR?main?TESTMAIN;main:; void main(void) C:0x000F 80FE SJMP main(C:000F) ;main()函数C:0x0011 00 NOP C:0x0012 00 NOP C:0x0013 00 NOP C:0x0014 00 NOP C:0x0015 00 NOP 现在分析上面的汇编程序就会明白c51程序是如何启动的。该程序有三个代码段;第一个代码段?C_STARTUP在0x0000地址,是CPU第一条指令的入口,它只有一条长跳转指令,直接跳到第二个代码段.第二个代码段?C_C51STARTUP是可重定位的段,该程序把内存清零,然后再设置CPU的堆栈,最后跳转到main()函数.第三个代码段就是main()函数,在keil c51编译器里main()的段地址名就是?C_START。还有一个IDATA数据段?STACK就是堆栈,?STACK用于设制CPU的堆栈起始地址,这是由keil编译器自动完成的/*/ 内容二:和函数有关的数值的存储/*/keil c51函数的返回值是存储在r0-r7中的。多字节变量在存储器里都是低地址存高位,高地址存低位。main()函数的局部变量都是放在存储器里的,不象别的函数先选寄存器r0-r7存放,如果不够用再存入存储器里。看下面的示例;c51程序;unsigned int SumXY(unsigned int X,Y);void main(void)unsigned int a,b,c; a=0x5500; b=0xaa; while (1) c=SumXY(a,b); unsigned int SumXY(unsigned int X,Y)unsigned int Z; Z=X+Y; return Z;编译后的反汇编代码列表;C:0x0000 020027 LJMP STARTUP1(C:0027) 4: void main(void) 5: unsigned int a,b,c; 6: a=0x5500; C:0x0003 750855 MOV 0x08,#0x55 ;ram地址0x08和0x09存放变量a=0x5500。C:0x0006 750900 MOV 0x09,#0x00 7: b=0xaa; C:0x0009 750A00 MOV 0x0A,#0x00 ;ram地址0x0A和0x0B存放变量b=0x00AA。C:0x000C 750BAA MOV 0x0B,#0xAA 8: while (1) 9: 10: c=SumXY(a,b); C:0x000F AD0B MOV R5,0x0B ;寄存器R4和R5传递变量a的值。C:0x0011 AC0A MOV R4,0x0AC:0x0013 AF09 MOV R7,0x09 ;寄存器R6和R7传递变量b的值。C:0x0015 AE08 MOV R6,0x08C:0x0017 120020 LCALL SumXY(C:0020) ;调用函数SumXY(a,b)求c=a+bC:0x001A 8E0C MOV 0x0C,R6 ;函数SumXY(a,b)返回的整型值存在R6和R7里,C:0x001C 8F0D MOV 0x0D,R7 ;把返回值存入变量c,ram地址0x0C和0x0D存放变量c 11: 12: 13: C:0x001E 80EF SJMP C:000F 14: unsigned int SumXY(unsigned int X,Y) 15: unsigned int Z; 16: Z=X+Y; C:0x0020 EF MOV A,R7 ;参数变量X放在寄存器R6和R7里C:0x0021 2D ADD A,R5 ;参数变量Y放在寄存器R4和R5里C:0x0022 FF MOV R7,AC:0x0023 EE MOV A,R6C:0x0024 3C ADDC A,R4 ;计算Z=X+Y; C:0x0025 FE MOV R6,A ;局部变量Z也放在寄存器R6和R7里 17: return Z; ;由寄存器R6和R7里返回函数的值C:0x0026 22 RET 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:0x0027 75810D MOV SP(0x81),#0x0D 155: LJMP ?C_START C:0x002A 020003 LJMP main(C:0003)/*/ 内容三:函数的入口地址,如何调用汇编函数,c和汇编的混合编程/*/c函数的函数名是一个指向函数的指针常量,它的值就是函数的入口地址。从汇编程序上看,函数名也是该汇编函数代码段的入口地址标号。调用汇编函数就是调用汇编函数的入口地址标号,但是要注意c函数名和汇编函数标号之间的转换规则。1. 不带参数的汇编函数标号和c函数名相同.2. 带参数的汇编函数标号在c函数名前加字符_,例如;如果c函数名是SumXY,汇编函数标号是_SumXY3. 再入函数的汇编函数标号在c函数名前加_?,例如;如果c函数名是DoTask,汇编函数标号是_?DoTask程序示例,该例有两个文件,一个文件是exam1.c,一个文件是funcasm.c主程序文件: exam1.c/声明外部汇编语言函数,和声明c函数方法相同。extern unsigned int SumXY(unsigned int X,Y); extern void Delay(unsigned char T);void main(void)unsigned int a,b,c; a=0x5500; b=0x00aa; while (1) Delay(100); c=SumXY(a,b); 混合编程文件: funcasm.c/c和汇编的混合编程演示./注意要把汇编语言函数放在文件前面。/求Z=X+Y的汇编语言函数,Z,X,Y是整型数。#pragma ASM PUBLIC _SumXY?PR?_SumXY?FUNCASM SEGMENT CODE RSEG ?PR?_SumXY?FUNCASM_SumXY: ;求Z=X+Y MOV A,R7 ;参数X放在寄存器R6和R7里 ADD A,R5 ;参数Y放在寄存器R4和R5里 MOV R7,A MOV A,R6 ADDC A,R4 ;扑鉠=X+Y; MOV R6,A ;局部变量Z也放在寄存器R6和R7里 RET #pragma ENDASM/c语言函数,延时函数。void Delay(unsigned char T)unsigned char i; for (i=0;iT;i+) for (i=0;iT;i+) 上面程序编译后的反汇编代码列表; C_STARTUP:C:0x0000 020041 LJMP STARTUP1(C:0041) main:/给变量a和b赋值 a=0x5500; b=0x00aa;C:0x0003 750855 MOV 0x08,#0x55C:0x0006 750900 MOV 0x09,#0x00C:0x0009 750A00 MOV 0x0A,#0x00C:0x000C 750BAA MOV 0x0B,#0xAA/调用延时函数Delay(100); C:0x000F 7F64 MOV R7,#0x64C:0x0011 120025 LCALL DELAY(C:0025)/求c=SumXY(a,b);C:0x0014 AD0B MOV R5,0x0BC:0x0016 AC0A MOV R4,0x0AC:0x0018 AF09 MOV R7,0x09C:0x001A AE08 MOV R6,0x08C:0x001C 12003A LCALL SUMXY(C:003A) ;调用汇编语言函数SumXY(unsigned int X,Y)C:0x001F 8E0C MOV 0x0C,R6C:0x0021 8F0D MOV 0x0D,R7C:0x0023 80EA SJMP C:000F/c语言延时函数的反汇编代码/void Delay(unsigned char T) DELAY:C:0x0025 E4 CLR AC:0x0026 FE MOV R6,A C0001:C:0x0027 EE MOV A,R6C:0x0028 C3 CLR CC:0x0029 9F SUBB A,R7C:0x002A 500D JNC C0007(C:0039)C:0x002C E4 CLR AC:0x002D FE MOV R6,A C0004:C:0x002E EE MOV A,R6C:0x002F C3 CLR CC:0x0030 9F SUBB A,R7C:0x0031 5003 JNC C0003(C:0036)C:0x0033 0E INC R6C:0x0034 80F8 SJMP C0004(C:002E) C0003:C:0x0036 0E INC R6C:0x0037 80EE SJMP C0001(C:0027) C0007:C:0x0039 22 RET /汇编语言函数SumXY(unsigned int X,Y)的反汇编代码,求Z=X+Y SUMXY:C:0x003A EF MOV A,R7C:0x003B 2D ADD A,R5C:0x003C FF MOV R7,AC:0x003D EE MOV A,R6C:0x003E 3C ADDC A,R4C:0x003F FE MOV R6,AC:0x0040 22 RET /程序启动代码; STARTUP1:C:0x0041 75810D MOV SP(0x81),#0x0DC:0x0044 020003 LJMP main(C:0003)参数传递规则例子:fun1(int a)/a是第一个参数,在R6,R7中传递.fun2(int b ,int c , int *d)/b在R6,R7中传递;C在R4,R5中传递;d在 R1,R2,R3中传递.fun3(long e ,long f)/e在R4-R7中传递;f不能在寄存器中传递,只能在参数传递段中传递.fun3(float g ,char h)/g在R4-R7中传递;h不能在寄存器中传递,只能在参数传递段中传递C语言和汇编语言的变量以及函数的接口问题在C和汇编混合编程的时候,存在C语言和汇编语言的变量以及函数的接口问题。在C程序中定义的变量,编译为.asm文件后,都被放进了.bss区,而且变量名的前面都带了一个下划线。在C程序中定义的函数,编译后在函数名前也带了一个下划线。例如:extern int num 就会变成 .bss _num, 1extern float nums5 就会变成 .bss _nums, 5extern void func ( ) 就会变成 _func,一、汇编和C的相互调用可以分以下几种情况:(1)汇编程序中访问c程序中的变量和函数。在汇编程序中,用_XX就可以访问C中的变量XX了。访问数组时,可以用_XX+偏移量来访问,如_XX+3访问了数组中的XX3。在汇编程序调用C函数时,如果没有参数传递,直接用_funcname 就可以了。如果有参数传递, 则函数中最左边的一个参数由寄存器A给出,其他的参数按顺序由堆栈给出。返回值是返回到A寄存器或者由A寄存器给出的地址。同时注意,为了能够让汇编语言 能访问到C语言中定义的变量和函数,他们必须声明为外部变量,即加extern 前缀。(2)c程序中访问汇编程序中的变量如果需要在c程序中访问汇编程序中的变量,则汇编程序中的变量名必须以下划线为首字符,并用global使之成为全局变量。
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030中国钉枪行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国野味皮制品行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国造纸及纸制品行业市场发展现状及发展趋势与投资前景研究报告
- 2025-2030中国软饮料行业市场深度调研及发展策略研究报告
- 2025-2030中国轮椅行业市场深度调研及竞争格局与投资研究报告
- 2025-2030中国足球护具行业市场发展趋势与前景展望战略研究报告
- 2025-2030中国超市行业经营效益及重点区域发展模式分析研究报告
- 2025-2030中国豆腐乳行业发展分析及投资前景预测研究报告
- 2025-2030中国观光农业行业市场发展现状及竞争格局与投资前景研究报告
- 2025-2030中国行间中耕机行业市场发展趋势与前景展望战略研究报告
- 贵州省语文中考2024-2025学年仿真试卷及答案解析
- 2024年国家林业和草原局华东调查规划设计院招聘高校毕业生10人历年(高频重点复习提升训练)共500题附带答案详解
- 武汉2024年湖北武汉音乐学院非事业编岗位招聘笔试历年典型考题及考点附答案解析
- 新人教小学数学六年级下册《用比例解决问题(二)》教学设计
- 交响音乐赏析智慧树知到期末考试答案章节答案2024年西安交通大学
- 2024年广东省惠州市惠城区中考二模物理试卷
- 2024年山东省青岛市部分学校九年级中考二模数学试题(含答案)
- 河南省郑州市中原区2023-2024学年三年级下学期期中考试数学试卷
- 日常保安服务投标技术方案(技术标)
- 行政复议法-形考作业1-国开(ZJ)-参考资料
- 中国军事武器
评论
0/150
提交评论