第 4 章 程序设计

24
4 4 第第第第 第第第第

Upload: ellery

Post on 21-Jan-2016

59 views

Category:

Documents


0 download

DESCRIPTION

第 4 章 程序设计. §4 .1 汇编语言程序设计. [ 例 4.1] 程序每隔一段时间从 A 口输出数据,驱动 LED 亮。. .INCLUDE handware.inc .RAM .VAR R_LedCounter; .VAR R_DelayCounter; .CODE .PUBLIC _main; _main: R1=0xFFFF; [P_IOA_Dir]=R1; [P_IOA_Attrib]=R1; R1=0x0000; [P_IOA_Data]=R1; [R_LedCounter]=R1;. L_MainLoop: - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 4 章  程序设计

第第 44 章 程序设计章 程序设计第第 44 章 程序设计章 程序设计

Page 2: 第 4 章  程序设计

§4.1 汇编语言程序设计§4.1 汇编语言程序设计

Page 3: 第 4 章  程序设计

[[ 例例 4.1] 4.1] 程序每隔一段时间从程序每隔一段时间从AA 口输出数据,驱动口输出数据,驱动 LEDLED 亮。亮。

.INCLUDE handware.inc.INCLUDE handware.inc

.RAM.RAM

.VAR R_LedCounter;.VAR R_LedCounter;

.VAR R_DelayCounter;.VAR R_DelayCounter;

.CODE.CODE

.PUBLIC _main;.PUBLIC _main;_main:_main:

R1=0xFFFF;R1=0xFFFF;[P_IOA_Dir]=R1;[P_IOA_Dir]=R1;[P_IOA_Attrib]=R1;[P_IOA_Attrib]=R1;R1=0x0000;R1=0x0000;[P_IOA_Data]=R1;[P_IOA_Data]=R1;[R_LedCounter]=R1;[R_LedCounter]=R1;

.INCLUDE handware.inc.INCLUDE handware.inc

.RAM.RAM

.VAR R_LedCounter;.VAR R_LedCounter;

.VAR R_DelayCounter;.VAR R_DelayCounter;

.CODE.CODE

.PUBLIC _main;.PUBLIC _main;_main:_main:

R1=0xFFFF;R1=0xFFFF;[P_IOA_Dir]=R1;[P_IOA_Dir]=R1;[P_IOA_Attrib]=R1;[P_IOA_Attrib]=R1;R1=0x0000;R1=0x0000;[P_IOA_Data]=R1;[P_IOA_Data]=R1;[R_LedCounter]=R1;[R_LedCounter]=R1;

L_MainLoop:L_MainLoop:R1= [R_LedCounter];R1= [R_LedCounter];[P_IOA_Data]=R1;[P_IOA_Data]=R1;R1= [R_LedCounter];R1= [R_LedCounter];R1+=1;R1+=1;[R_LedCounter]=R1;[R_LedCounter]=R1;R1=0;R1=0;[R_DelayCounter]=R1;[R_DelayCounter]=R1;CALL F_Delay;CALL F_Delay;JMP L_MainLoop;JMP L_MainLoop;

L_MainLoop:L_MainLoop:R1= [R_LedCounter];R1= [R_LedCounter];[P_IOA_Data]=R1;[P_IOA_Data]=R1;R1= [R_LedCounter];R1= [R_LedCounter];R1+=1;R1+=1;[R_LedCounter]=R1;[R_LedCounter]=R1;R1=0;R1=0;[R_DelayCounter]=R1;[R_DelayCounter]=R1;CALL F_Delay;CALL F_Delay;JMP L_MainLoop;JMP L_MainLoop;

Page 4: 第 4 章  程序设计

数制及数据类型数制及数据类型数制数制 数的表示数的表示二进制二进制 BB 后缀后缀八进制八进制 O/QO/Q 后缀后缀十进制十进制 D/D/ 无后缀无后缀十六进制十六进制 HH 后缀或后缀或 0x0x 、、 $$ 前缀前缀ASCIIASCII 字符串字符串 用单或双引号括起来用单或双引号括起来

数据类型数据类型 位数位数 无符号数无符号数 符号数符号数字(字( DWDW )) 1616 0-655350-65535 -32768 ~ +32767-32768 ~ +32767

双字(双字( DDDD )) 3232 0-42949672950-4294967295 -2147483648 ~ +2147483647-2147483648 ~ +2147483647

单精度(单精度( FLOATFLOAT )) 3232 IEEEIEEE 格式浮点数格式浮点数双精度(双精度( DOUBLDOUBLEE ))

6464 IEEEIEEE 格式浮点数格式浮点数

Page 5: 第 4 章  程序设计

µµ’nSP’nSPTMTM 算符及优先次序算符及优先次序优先级优先级 运算符运算符 说明说明

notnot 、、 ~~ 、!、! 逻辑算符逻辑算符 -- 真真 // 假假-- 、、 ++ 正负操作符正负操作符%% 、、 // 、、 **

-- 、、 ++ 加减运算符加减运算符>>>> 、、 <<<< 右移、左移右移、左移<< 、、 <=<= 、、 >> 、、 >=>=

!=!= 、、 = == =

^̂ 或或 xorxor 、、 && 或或 andand 、、 ||或或 oror

按位操作按位操作

|||| 、、 &&&& 逻辑算符逻辑算符 -- 真真 // 假假

Page 6: 第 4 章  程序设计

全局标号与局部标号全局标号与局部标号全局标号与局部标号全局标号与局部标号标号 是一种符号地址。是指令或数据的起

始地址。全局标号 各程序段都能调用。以字母或“ _”

开头 , 以“ :” 结束。局部标号 只在该程序段调用。以“ ?” 为前缀

或后缀。

标号 是一种符号地址。是指令或数据的起

始地址。全局标号 各程序段都能调用。以字母或“ _”

开头 , 以“ :” 结束。局部标号 只在该程序段调用。以“ ?” 为前缀

或后缀。

Page 7: 第 4 章  程序设计

汇编语言汇编语言程序举例程序举例

Page 8: 第 4 章  程序设计

.INCLUDE handware.inc.INCLUDE handware.inc

.RAM.RAM

.VAR .VAR R_LedCounterR_LedCounter;;

.VAR .VAR R_DelayCounterR_DelayCounter;;

.CODE.CODE

.PUBLIC _main;.PUBLIC _main;_main:_main:

R1=0xFFFF;R1=0xFFFF; //PIOA//PIOA 口为同相低电平输出口为同相低电平输出[P_IOA_Dir]=R1;[P_IOA_Dir]=R1;[P_IOA_Attrib]=R1;[P_IOA_Attrib]=R1;R1=0x0000;R1=0x0000;[P_IOA_Data]=R1;[P_IOA_Data]=R1;[R_LedCounter]=R1;[R_LedCounter]=R1; //// 清变量清变量 R_LedCounterR_LedCounter

.INCLUDE handware.inc.INCLUDE handware.inc

.RAM.RAM

.VAR .VAR R_LedCounterR_LedCounter;;

.VAR .VAR R_DelayCounterR_DelayCounter;;

.CODE.CODE

.PUBLIC _main;.PUBLIC _main;_main:_main:

R1=0xFFFF;R1=0xFFFF; //PIOA//PIOA 口为同相低电平输出口为同相低电平输出[P_IOA_Dir]=R1;[P_IOA_Dir]=R1;[P_IOA_Attrib]=R1;[P_IOA_Attrib]=R1;R1=0x0000;R1=0x0000;[P_IOA_Data]=R1;[P_IOA_Data]=R1;[R_LedCounter]=R1;[R_LedCounter]=R1; //// 清变量清变量 R_LedCounterR_LedCounter

什么寻址什么寻址方式?方式?

[[ 例例 4.3] 4.3] 程序每隔一段时间从程序每隔一段时间从AA 口输出数据,驱动口输出数据,驱动 LEDLED 亮。亮。

L_MainLoop:L_MainLoop:R1= [R_LedCounter];R1= [R_LedCounter]; //// 从变量从变量 R_LedCounterR_LedCounter 处获处获

取取[P_IOA_Data]=R1;[P_IOA_Data]=R1; //// 显示值,显示。显示值,显示。R1= [R_LedCounter];R1= [R_LedCounter]; //// 修改变量修改变量 R_LedCounterR_LedCounter ,,R1+=1;R1+=1;[R_LedCounter]=R1;[R_LedCounter]=R1; //// 使变量使变量 R_LedCounterR_LedCounter 加加 11 。。R1=0;R1=0;[R_DelayCounter]=R1;[R_DelayCounter]=R1; //// 清变量清变量 R_DelayCounterR_DelayCounterCALL F_Delay;CALL F_Delay;JMP L_MainLoop;JMP L_MainLoop;

L_MainLoop:L_MainLoop:R1= [R_LedCounter];R1= [R_LedCounter]; //// 从变量从变量 R_LedCounterR_LedCounter 处获处获

取取[P_IOA_Data]=R1;[P_IOA_Data]=R1; //// 显示值,显示。显示值,显示。R1= [R_LedCounter];R1= [R_LedCounter]; //// 修改变量修改变量 R_LedCounterR_LedCounter ,,R1+=1;R1+=1;[R_LedCounter]=R1;[R_LedCounter]=R1; //// 使变量使变量 R_LedCounterR_LedCounter 加加 11 。。R1=0;R1=0;[R_DelayCounter]=R1;[R_DelayCounter]=R1; //// 清变量清变量 R_DelayCounterR_DelayCounterCALL F_Delay;CALL F_Delay;JMP L_MainLoop;JMP L_MainLoop;

LEDLED 显示什么?显示什么?LEDLED 显示什么?显示什么?//*********//********* 延时子程序。 延时子程序。 ***********************//***********************//F_Delay:F_Delay:L_DelayLoop:L_DelayLoop:

R1=0x0001;R1=0x0001; //4 //4[P_Watchdog_Clear]=R1; //7[P_Watchdog_Clear]=R1; //7R1=[R_DelayCounter];R1=[R_DelayCounter]; //7 //7 ,变量,变量 R_DelayCounterR_DelayCounter+1+1R1+=1;R1+=1; //3 //3[R_DelayCounter]=R1;[R_DelayCounter]=R1; //7 //7JNZ L_DelayLoop;JNZ L_DelayLoop; //5 //5RETF;RETF;

//*********//********* 延时子程序。 延时子程序。 ***********************//***********************//F_Delay:F_Delay:L_DelayLoop:L_DelayLoop:

R1=0x0001;R1=0x0001; //4 //4[P_Watchdog_Clear]=R1; //7[P_Watchdog_Clear]=R1; //7R1=[R_DelayCounter];R1=[R_DelayCounter]; //7 //7 ,变量,变量 R_DelayCounterR_DelayCounter+1+1R1+=1;R1+=1; //3 //3[R_DelayCounter]=R1;[R_DelayCounter]=R1; //7 //7JNZ L_DelayLoop;JNZ L_DelayLoop; //5 //5RETF;RETF;

Page 9: 第 4 章  程序设计

.IRAM.IRAMArray: .DW 40, 6, 32, 12, 9, 24, 28;Array: .DW 40, 6, 32, 12, 9, 24, 28;.VAR C_Flag;.VAR C_Flag;.CODE.CODE.PUBLIC _main;.PUBLIC _main;_main:_main:L_Sort:L_Sort:

BP=Array;BP=Array;R1=0x0006;R1=0x0006;R4=0;R4=0; //// 进行下轮排序之前,清标志单元。进行下轮排序之前,清标志单元。[C_ Flag]=R4;[C_ Flag]=R4;

L_Loop:L_Loop:R3=[BP];R3=[BP]; //// 相邻单元比较:取第一个数,相邻单元比较:取第一个数,CMP R3, [BP+1];CMP R3, [BP+1]; //// 与第二个数比较。与第二个数比较。

.IRAM.IRAMArray: .DW 40, 6, 32, 12, 9, 24, 28;Array: .DW 40, 6, 32, 12, 9, 24, 28;.VAR C_Flag;.VAR C_Flag;.CODE.CODE.PUBLIC _main;.PUBLIC _main;_main:_main:L_Sort:L_Sort:

BP=Array;BP=Array;R1=0x0006;R1=0x0006;R4=0;R4=0; //// 进行下轮排序之前,清标志单元。进行下轮排序之前,清标志单元。[C_ Flag]=R4;[C_ Flag]=R4;

L_Loop:L_Loop:R3=[BP];R3=[BP]; //// 相邻单元比较:取第一个数,相邻单元比较:取第一个数,CMP R3, [BP+1];CMP R3, [BP+1]; //// 与第二个数比较。与第二个数比较。

什么寻址方式 ?

[[ 例例 4.4]4.4] 冒泡排冒泡排序序

JB L_Next;JB L_Next; //// 小于转移,顺序不变。小于转移,顺序不变。R2=[BP+1];R2=[BP+1]; //// 否则,交换顺序:否则,交换顺序:[BP]=R2;[BP]=R2; //// 较小值存于第一单元较小值存于第一单元[BP+1]=R3;[BP+1]=R3; //// 较大值存于第二单元。较大值存于第二单元。R3=0x0001;R3=0x0001; //// 置位标志单元。置位标志单元。[C_Flag]=R3;[C_Flag]=R3;

L_Next:L_Next:BP=BP+1;BP=BP+1; //BP//BP 指向下第二个单元。指向下第二个单元。R1-=1;R1-=1; //// 计数器减计数器减 11 。判断是否到最后一个单元?。判断是否到最后一个单元?JNZ L_Loop;JNZ L_Loop; //// 否,继续比较余下的数。否,继续比较余下的数。R4=[C_Flag];R4=[C_Flag]; //// 上述排序结束。标志单元上述排序结束。标志单元 =0=0 ??JNZ L_Sort;JNZ L_Sort; ////00 ,可能排序未结束。再进行一次。,可能排序未结束。再进行一次。

L_MainLoop:L_MainLoop:JMP L_MainLoop;JMP L_MainLoop;

JB L_Next;JB L_Next; //// 小于转移,顺序不变。小于转移,顺序不变。R2=[BP+1];R2=[BP+1]; //// 否则,交换顺序:否则,交换顺序:[BP]=R2;[BP]=R2; //// 较小值存于第一单元较小值存于第一单元[BP+1]=R3;[BP+1]=R3; //// 较大值存于第二单元。较大值存于第二单元。R3=0x0001;R3=0x0001; //// 置位标志单元。置位标志单元。[C_Flag]=R3;[C_Flag]=R3;

L_Next:L_Next:BP=BP+1;BP=BP+1; //BP//BP 指向下第二个单元。指向下第二个单元。R1-=1;R1-=1; //// 计数器减计数器减 11 。判断是否到最后一个单元?。判断是否到最后一个单元?JNZ L_Loop;JNZ L_Loop; //// 否,继续比较余下的数。否,继续比较余下的数。R4=[C_Flag];R4=[C_Flag]; //// 上述排序结束。标志单元上述排序结束。标志单元 =0=0 ??JNZ L_Sort;JNZ L_Sort; ////00 ,可能排序未结束。再进行一次。,可能排序未结束。再进行一次。

L_MainLoop:L_MainLoop:JMP L_MainLoop;JMP L_MainLoop;

程序要进行多少程序要进行多少次次 L_SortL_Sort 循环?循环?

程序要进行多少程序要进行多少次次 L_SortL_Sort 循环?循环?

原顺序:原顺序: 4040 ,, 66 ,, 3232 ,, 1212 ,, 99 ,, 2424 ,,2828

原顺序:原顺序: 4040 ,, 66 ,, 3232 ,, 1212 ,, 99 ,, 2424 ,,2828排序 排序 1 1 :: 66 ,, 3232 ,, 1212 ,, 99 ,, 2424 ,, 2288 ,, 4040

排序 排序 1 1 :: 66 ,, 3232 ,, 1212 ,, 99 ,, 2424 ,, 2288 ,, 4040排序 排序 2 2 :: 66 ,, 1212 ,, 99 ,, 2424 ,, 2828 ,, 3322 ,, 4040

排序 排序 2 2 :: 66 ,, 1212 ,, 99 ,, 2424 ,, 2828 ,, 3322 ,, 4040排序 排序 3 3 :: 66 ,, 99 ,, 1212 ,, 2424 ,, 2828 ,, 3322 ,, 4040

排序 排序 3 3 :: 66 ,, 99 ,, 1212 ,, 2424 ,, 2828 ,, 3322 ,, 4040

Page 10: 第 4 章  程序设计

子程序的结构子程序的结构子程序名 子程序名 .PROC .PROC

程序体程序体RETFRETF

.ENDP.ENDP现场保护现场保护 -- 返回地址、寄存器。返回地址、寄存器。参数传递参数传递

通过寄存器传递—通过寄存器传递— R1~R4R1~R4 通过变量传递—不同文件使用变量时,通过变量传递—不同文件使用变量时, PUBLICPUBLIC 声明全声明全

局变量,使用此变量的其它文件,应该用局变量,使用此变量的其它文件,应该用 EXTERNALEXTERNAL声明为外部变量。声明为外部变量。

通过堆栈传递通过堆栈传递

子程序的结构子程序的结构子程序名 子程序名 .PROC .PROC

程序体程序体RETFRETF

.ENDP.ENDP现场保护现场保护 -- 返回地址、寄存器。返回地址、寄存器。参数传递参数传递

通过寄存器传递—通过寄存器传递— R1~R4R1~R4 通过变量传递—不同文件使用变量时,通过变量传递—不同文件使用变量时, PUBLICPUBLIC 声明全声明全

局变量,使用此变量的其它文件,应该用局变量,使用此变量的其它文件,应该用 EXTERNALEXTERNAL声明为外部变量。声明为外部变量。

通过堆栈传递通过堆栈传递

关于子程序关于子程序

Page 11: 第 4 章  程序设计

//// 函数:函数: F_Abs_32()F_Abs_32()//// 语法语法 : void F_Abs_32( int A , int B ): void F_Abs_32( int A , int B )//// 描述描述 : : 求求 3232 位符号数的绝对值位符号数的绝对值//// 参数参数 : R4R3=: R4R3= 符号数符号数//// 返回返回 : R2R1=: R2R1= 绝对值绝对值//=====================================//=====================================.CODE.CODE.PUBLIC F_Abs_32.PUBLIC F_Abs_32F_Abs_32F_Abs_32 ::

R1=R3R1=R3;;R2=R4R2=R4;;JMI JMI ?neg?neg ;; //// 为负转移为负转移RETFRETF ;;

?neg?neg ::R1^=0xFFFFR1^=0xFFFF ;; //// 取反取反R2^=0xFFFFR2^=0xFFFF ;;R1+=1R1+=1;; //// 加加 11R2+=0R2+=0,, CarryCarry ;;RETFRETF ;;

//// 函数:函数: F_Abs_32()F_Abs_32()//// 语法语法 : void F_Abs_32( int A , int B ): void F_Abs_32( int A , int B )//// 描述描述 : : 求求 3232 位符号数的绝对值位符号数的绝对值//// 参数参数 : R4R3=: R4R3= 符号数符号数//// 返回返回 : R2R1=: R2R1= 绝对值绝对值//=====================================//=====================================.CODE.CODE.PUBLIC F_Abs_32.PUBLIC F_Abs_32F_Abs_32F_Abs_32 ::

R1=R3R1=R3;;R2=R4R2=R4;;JMI JMI ?neg?neg ;; //// 为负转移为负转移RETFRETF ;;

?neg?neg ::R1^=0xFFFFR1^=0xFFFF ;; //// 取反取反R2^=0xFFFFR2^=0xFFFF ;;R1+=1R1+=1;; //// 加加 11R2+=0R2+=0,, CarryCarry ;;RETFRETF ;;

[[ 例例 4.5] 4.5] 求求 3232 位位符号数的绝对值。符号数的绝对值。[[ 例例 4.5] 4.5] 求求 3232 位位符号数的绝对值。符号数的绝对值。

Page 12: 第 4 章  程序设计

• 关于关于 GCCGCC

• GCCGCC 对对 ANSI-CANSI-C基本数据类型的支持基本数据类型的支持数据类型数据类型 数据长度数据长度 (( 位数位数 ) ) 值域值域Int Int 1616 -32768~-32768~ +32767 32767 long int long int 32 32 -2147483648~+2147483647 -2147483648~+2147483647 unsigned int unsigned int 16 16 0~65535 0~65535 Unsigned Unsigned long long

32 32 0~4294967295 0~4294967295 float float 32 32 以以 IEEEIEEE 格式表示的格式表示的 3232 位浮点数位浮点数double double 64 64 以以 IEEEIEEE 格式表示的格式表示的 6464 位浮点数 位浮点数

§4§4.2C.2C 语言程序设计语言程序设计GNC CCGNC CC 是一个功能非常强大的跨平台 是一个功能非常强大的跨平台 C C 编译器,它对 编译器,它对 C C 语言提供了很多扩展,这些扩展对优化、目标代码布局、语言提供了很多扩展,这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。更安全的检查等方面提供了很强的支持。

GNC CCGNC CC 是一个功能非常强大的跨平台 是一个功能非常强大的跨平台 C C 编译器,它对 编译器,它对 C C 语言提供了很多扩展,这些扩展对优化、目标代码布局、语言提供了很多扩展,这些扩展对优化、目标代码布局、更安全的检查等方面提供了很强的支持。更安全的检查等方面提供了很强的支持。

Page 13: 第 4 章  程序设计

#include “hardware.h”#include “hardware.h”void Delay()void Delay(){{

unsigned int I ;unsigned int I ;for (I=0; I<32768; I++){}for (I=0; I<32768; I++){}

}}int main()int main() {{ int LedCounter=0;int LedCounter=0;

int temp;int temp;SP_Init_IOA(0xffff, 0xffff, 0xffff)SP_Init_IOA(0xffff, 0xffff, 0xffff)while(1)while(1){{

SP_Export(PSP_Export(Portort_ioa_Data, LedCounter);_ioa_Data, LedCounter); LedCounter++;LedCounter++; Delay();Delay();

}} }}

#include “hardware.h”#include “hardware.h”void Delay()void Delay(){{

unsigned int I ;unsigned int I ;for (I=0; I<32768; I++){}for (I=0; I<32768; I++){}

}}int main()int main() {{ int LedCounter=0;int LedCounter=0;

int temp;int temp;SP_Init_IOA(0xffff, 0xffff, 0xffff)SP_Init_IOA(0xffff, 0xffff, 0xffff)while(1)while(1){{

SP_Export(PSP_Export(Portort_ioa_Data, LedCounter);_ioa_Data, LedCounter); LedCounter++;LedCounter++; Delay();Delay();

}} }}

////////////////////////////////////////////////////////////////// Function: I/O Port A configuration// void SP_Inti_IOA(int Dir, int Data, int Attrib)////////////////////////////////////////////////////////////////_SP_Init_IOA: .PROC

PUSH BP TO [SP] BP = SP + 1 PUSH R1 TO [SP] R1 = [BP+3] // Port direction[P_IOA_Dir] = R1 R1 = [BP+4] [P_IOA_Data] = R1 R1 = [BP+5] [P_IOA_Attrib] = R1 POP R1 FROM [SP] POP BP FROM [SP] RETF .ENDP

////////////////////////////////////////////////////////////////// Function: I/O Port A configuration// void SP_Inti_IOA(int Dir, int Data, int Attrib)////////////////////////////////////////////////////////////////_SP_Init_IOA: .PROC

PUSH BP TO [SP] BP = SP + 1 PUSH R1 TO [SP] R1 = [BP+3] // Port direction[P_IOA_Dir] = R1 R1 = [BP+4] [P_IOA_Data] = R1 R1 = [BP+5] [P_IOA_Attrib] = R1 POP R1 FROM [SP] POP BP FROM [SP] RETF .ENDP

[[ 例例 4.6]4.6] 用用 CC 语言编写用语言编写用 IOIO控制闪灯控制闪灯程序程序

_SP_Export: _SP_Export: .PROC.PROCPUSH BP,BP TO [SP] PUSH BP,BP TO [SP] BP = SP + 1 BP = SP + 1 PUSH R1,R2 TO [SP] PUSH R1,R2 TO [SP] R1 = [BP+3] R1 = [BP+3] // Port Number// Port NumberR2 = [BP+4] R2 = [BP+4] // Value// Value[R1] = R2 [R1] = R2 //// 输出输出POP R1,R2 FROM [SP] POP R1,R2 FROM [SP] POP BP,BP FROM [SP] POP BP,BP FROM [SP] RETF RETF

.ENDP.ENDP

_SP_Export: _SP_Export: .PROC.PROCPUSH BP,BP TO [SP] PUSH BP,BP TO [SP] BP = SP + 1 BP = SP + 1 PUSH R1,R2 TO [SP] PUSH R1,R2 TO [SP] R1 = [BP+3] R1 = [BP+3] // Port Number// Port NumberR2 = [BP+4] R2 = [BP+4] // Value// Value[R1] = R2 [R1] = R2 //// 输出输出POP R1,R2 FROM [SP] POP R1,R2 FROM [SP] POP BP,BP FROM [SP] POP BP,BP FROM [SP] RETF RETF

.ENDP.ENDP

与与 [[ 例例 4.3]4.3] 程程序功能比较,序功能比较,有何异同?有何异同?

与与 [[ 例例 4.3]4.3] 程程序功能比较,序功能比较,有何异同?有何异同?

Page 14: 第 4 章  程序设计

§4§4.3 C.3 C 和汇编混合编程和汇编混合编程§4§4.3 C.3 C 和汇编混合编程和汇编混合编程

Page 15: 第 4 章  程序设计

11 、程序调用协议、程序调用协议 ::调用子程序间的参数传递; 调用子程序间的参数传递;

调用子程序或函数的参数传递调用子程序或函数的参数传递 (( 堆栈堆栈 ));;子程序或函数的返回值 子程序或函数的返回值 ((R2R2R1)R1);;堆栈结构与维护。堆栈结构与维护。由于由于 CC 编译器产生的所有标号都以下划线编译器产生的所有标号都以下划线““ _”_” 为前缀,而为前缀,而 CC 程序在调用汇编程序程序在调用汇编程序时要求汇编程序名也以下划线时要求汇编程序名也以下划线““ _”_” 为前为前缀。 缀。

11 、程序调用协议、程序调用协议 ::调用子程序间的参数传递; 调用子程序间的参数传递;

调用子程序或函数的参数传递调用子程序或函数的参数传递 (( 堆栈堆栈 ));;子程序或函数的返回值 子程序或函数的返回值 ((R2R2R1)R1);;堆栈结构与维护。堆栈结构与维护。由于由于 CC 编译器产生的所有标号都以下划线编译器产生的所有标号都以下划线““ _”_” 为前缀,而为前缀,而 CC 程序在调用汇编程序程序在调用汇编程序时要求汇编程序名也以下划线时要求汇编程序名也以下划线““ _”_” 为前为前缀。 缀。

§4.3.2 §4.3.2 CC 与汇编语言的交叉调用与汇编语言的交叉调用§4.3.2 §4.3.2 CC 与汇编语言的交叉调用与汇编语言的交叉调用

子程序或子程序或函数空间函数空间

返回地址返回地址

参数参数

Page 16: 第 4 章  程序设计

CC 语言调用汇编程序语言调用汇编程序main( )main( )

{{

int ret=0int ret=0

ret=ret=init_IOAinit_IOA(0x0000, 0x00FF, 0xFFFF);(0x0000, 0x00FF, 0xFFFF);

if (ret==0x01);if (ret==0x01);

}}

main( )main( )

{{

int ret=0int ret=0

ret=ret=init_IOAinit_IOA(0x0000, 0x00FF, 0xFFFF);(0x0000, 0x00FF, 0xFFFF);

if (ret==0x01);if (ret==0x01);

}}

.public .public _init_IOA_init_IOA

_init_IOA:_init_IOA:

push bp to [sp]push bp to [sp]

bpbp=sp+1=sp+1

r1=[bp+3]r1=[bp+3]

r2=[bp+4]r2=[bp+4]

r3=[bp+5]r3=[bp+5]

…… ……

r1=0x01 //r1=0x01 // 返回值。返回值。 pop bp from [sp]pop bp from [sp]

retfretf

BPBP

PCPC

SRSR

0x00000x0000

0x00FF0x00FF

0xFFFF0xFFFF调用前调用前 SSPP

调用后调用后 SSPP

第第 11 个参数个参数第第 22 个参数个参数第第 33 个参数个参数

bPbP

函数调用后的返回值,16 位放在 R1中, 32 位放在 R2 、 R1中。

函数调用后的返回值,16 位放在 R1中, 32 位放在 R2 、 R1中。

//// 取取第第 11 个参数个参数//// 取取第第 22 个参数个参数//// 取取第第 33 个参数个参数

第第 11 个参数个参数 第第 22 个参数个参数 第第 33 个参数个参数

// 处理程序

Page 17: 第 4 章  程序设计

[例[例 4.114.11]]

//***************************************************************///***************************************************************/// // 描述: 测试函数的返回值描述: 测试函数的返回值// // 日期: 日期: 2002/12/112002/12/11//***************************************************************///***************************************************************/int F_Sub_Asm1(void); //int F_Sub_Asm1(void); // 声明要调用的函数的函数原型声明要调用的函数的函数原型long int F_Sub_Asm2(void); //long int F_Sub_Asm2(void); // 声明要调用的函数的函数原型声明要调用的函数的函数原型//===============================================================//===============================================================// // 函数: 函数: main()main()// // 描述:主函数描述:主函数//===============================================================//===============================================================int main(){int main(){int i;int i;long int j;long int j;while(1){while(1){i = F_Sub_Asm1();i = F_Sub_Asm1();j = F_Sub_Asm2();j = F_Sub_Asm2();}}return 0;return 0;}}

//***************************************************************///***************************************************************/// // 描述: 测试函数的返回值描述: 测试函数的返回值// // 日期: 日期: 2002/12/112002/12/11//***************************************************************///***************************************************************/int F_Sub_Asm1(void); //int F_Sub_Asm1(void); // 声明要调用的函数的函数原型声明要调用的函数的函数原型long int F_Sub_Asm2(void); //long int F_Sub_Asm2(void); // 声明要调用的函数的函数原型声明要调用的函数的函数原型//===============================================================//===============================================================// // 函数: 函数: main()main()// // 描述:主函数描述:主函数//===============================================================//===============================================================int main(){int main(){int i;int i;long int j;long int j;while(1){while(1){i = F_Sub_Asm1();i = F_Sub_Asm1();j = F_Sub_Asm2();j = F_Sub_Asm2();}}return 0;return 0;}}

.code.code//===================================//===================================//// 函数函数 : F_Sub_Asm1(): F_Sub_Asm1()//// 语法:语法: void F_Sub_Asm1void F_Sub_Asm1 (( voidvoid ))//// 描述:整形返回值测试描述:整形返回值测试//// 参数:无参数:无//// 返回:整形值。返回:整形值。//====================================//====================================.PUBLIC _F_Sub_Asm1.PUBLIC _F_Sub_Asm1_F_Sub_Asm1:_F_Sub_Asm1:R1 = 0xaabb;R1 = 0xaabb;R2 = 0x5555;R2 = 0x5555;RETF;RETF;//====================================//====================================//// 函数函数 : F_Sub_Asm2(): F_Sub_Asm2()//// 语法:语法: void F_Sub_Asm2void F_Sub_Asm2 (( voidvoid ))//// 描述:长整型值返回值测试描述:长整型值返回值测试//// 参数:无参数:无//// 返回:一个长整型值返回:一个长整型值//====================================//========================================.PUBLIC _F_Sub_Asm2.PUBLIC _F_Sub_Asm2_F_Sub_Asm2:_F_Sub_Asm2:R1 = 0xaabb;R1 = 0xaabb;R2 = 0xffcc;R2 = 0xffcc;RETF;RETF;

.code.code//===================================//===================================//// 函数函数 : F_Sub_Asm1(): F_Sub_Asm1()//// 语法:语法: void F_Sub_Asm1void F_Sub_Asm1 (( voidvoid ))//// 描述:整形返回值测试描述:整形返回值测试//// 参数:无参数:无//// 返回:整形值。返回:整形值。//====================================//====================================.PUBLIC _F_Sub_Asm1.PUBLIC _F_Sub_Asm1_F_Sub_Asm1:_F_Sub_Asm1:R1 = 0xaabb;R1 = 0xaabb;R2 = 0x5555;R2 = 0x5555;RETF;RETF;//====================================//====================================//// 函数函数 : F_Sub_Asm2(): F_Sub_Asm2()//// 语法:语法: void F_Sub_Asm2void F_Sub_Asm2 (( voidvoid ))//// 描述:长整型值返回值测试描述:长整型值返回值测试//// 参数:无参数:无//// 返回:一个长整型值返回:一个长整型值//====================================//========================================.PUBLIC _F_Sub_Asm2.PUBLIC _F_Sub_Asm2_F_Sub_Asm2:_F_Sub_Asm2:R1 = 0xaabb;R1 = 0xaabb;R2 = 0xffcc;R2 = 0xffcc;RETF;RETF;

Page 18: 第 4 章  程序设计

[例[例 4.124.12 ]在]在 IOAIOA 口上以口上以 2S2S 的速率的速率闪烁闪烁

//************************************///************************************/// // 描述: 描述: CC 语言与汇编混合编程举例语言与汇编混合编程举例//************************************///************************************/unsigned int unsigned int TimeCountTimeCount = 0; = 0;int main()int main(){{ TimeCount = 0;TimeCount = 0; F_InitIOA(0xFFFF,0xFFFF,0x0000); // F_InitIOA(0xFFFF,0xFFFF,0x0000); //初始化初始化 IOAIOA 口带数据缓冲低电平输出口带数据缓冲低电平输出 SystemInit(); //SystemInit(); //系统初始化系统初始化 while(1)while(1) { {

if(if(TimeCountTimeCount<=4)<=4)LightOff(); //IOALightOff(); //IOA 口口 LEDLED熄灭熄灭

else if(else if(TimeCountTimeCount<=7)<=7)LightOn(); //IOALightOn(); //IOA 口口 LEDLED 亮亮

elseelse TimeCountTimeCount=0;=0; } }}}

//************************************///************************************/// // 描述: 描述: CC 语言与汇编混合编程举例语言与汇编混合编程举例//************************************///************************************/unsigned int unsigned int TimeCountTimeCount = 0; = 0;int main()int main(){{ TimeCount = 0;TimeCount = 0; F_InitIOA(0xFFFF,0xFFFF,0x0000); // F_InitIOA(0xFFFF,0xFFFF,0x0000); //初始化初始化 IOAIOA 口带数据缓冲低电平输出口带数据缓冲低电平输出 SystemInit(); //SystemInit(); //系统初始化系统初始化 while(1)while(1) { {

if(if(TimeCountTimeCount<=4)<=4)LightOff(); //IOALightOff(); //IOA 口口 LEDLED熄灭熄灭

else if(else if(TimeCountTimeCount<=7)<=7)LightOn(); //IOALightOn(); //IOA 口口 LEDLED 亮亮

elseelse TimeCountTimeCount=0;=0; } }}}

//System.asm //System.asm 汇编程序汇编程序.INCLUDE hardware.inc.INCLUDE hardware.inc.CODE.CODE//============================//============================//// 函数函数 : SystemInit(): SystemInit()//// 语法:语法: void SystemInitvoid SystemInit (( voidvoid ))//// 描述:系统初始化描述:系统初始化//// 参数:无参数:无//// 返回:无返回:无//===========================//===========================.PUBLIC _SystemInit; //.PUBLIC _SystemInit; //系统初始化系统初始化_SystemInit: .PROC_SystemInit: .PROCR1=0x0004 //R1=0x0004 // 开开 2Hz2Hz 中断中断[P_INT_Ctrl]=R1[P_INT_Ctrl]=R1IRQ ONIRQ ONRETF;RETF;.ENDP;.ENDP;

//System.asm //System.asm 汇编程序汇编程序.INCLUDE hardware.inc.INCLUDE hardware.inc.CODE.CODE//============================//============================//// 函数函数 : SystemInit(): SystemInit()//// 语法:语法: void SystemInitvoid SystemInit (( voidvoid ))//// 描述:系统初始化描述:系统初始化//// 参数:无参数:无//// 返回:无返回:无//===========================//===========================.PUBLIC _SystemInit; //.PUBLIC _SystemInit; //系统初始化系统初始化_SystemInit: .PROC_SystemInit: .PROCR1=0x0004 //R1=0x0004 // 开开 2Hz2Hz 中断中断[P_INT_Ctrl]=R1[P_INT_Ctrl]=R1IRQ ONIRQ ONRETF;RETF;.ENDP;.ENDP;

//============================//============================//// 函数函数 : F_InitIOA(): F_InitIOA()//// 语法:语法: void F_InitIOAvoid F_InitIOA (( voidvoid ))//// 描述:描述: IOIO 口初始化口初始化//// 参数:无参数:无//// 返回:无返回:无//============================//============================.PUBLIC _F_InitIOA; //.PUBLIC _F_InitIOA; //初始化初始化 IOAIOA 口口_F_InitIOA: .PROC_F_InitIOA: .PROCPUSH BP TO [SP];PUSH BP TO [SP];BP=SP+1;BP=SP+1;R1=[BP+3];R1=[BP+3];[P_IOA_Dir]=R1;[P_IOA_Dir]=R1;R1=[BP+4];R1=[BP+4];[P_IOA_Attrib]=R1;[P_IOA_Attrib]=R1;R1=[BP+5];R1=[BP+5];[P_IOA_Data]=R1;[P_IOA_Data]=R1;POP BP FROM [SP];POP BP FROM [SP];RETF;RETF;.ENDP;.ENDP;

//============================//============================//// 函数函数 : F_InitIOA(): F_InitIOA()//// 语法:语法: void F_InitIOAvoid F_InitIOA (( voidvoid ))//// 描述:描述: IOIO 口初始化口初始化//// 参数:无参数:无//// 返回:无返回:无//============================//============================.PUBLIC _F_InitIOA; //.PUBLIC _F_InitIOA; //初始化初始化 IOAIOA 口口_F_InitIOA: .PROC_F_InitIOA: .PROCPUSH BP TO [SP];PUSH BP TO [SP];BP=SP+1;BP=SP+1;R1=[BP+3];R1=[BP+3];[P_IOA_Dir]=R1;[P_IOA_Dir]=R1;R1=[BP+4];R1=[BP+4];[P_IOA_Attrib]=R1;[P_IOA_Attrib]=R1;R1=[BP+5];R1=[BP+5];[P_IOA_Data]=R1;[P_IOA_Data]=R1;POP BP FROM [SP];POP BP FROM [SP];RETF;RETF;.ENDP;.ENDP;

//=============================//=============================//// 函数函数 : LightOff(): LightOff()//// 语法:语法: void LightOffvoid LightOff(( voidvoid ))//// 描述:熄灭描述:熄灭 ledled//// 参数:无参数:无//// 返回:无返回:无//=============================//=============================.PUBLIC _LightOff; //IOA.PUBLIC _LightOff; //IOA 口口 LEDLED熄灭熄灭_LightOff: .PROC_LightOff: .PROCR1= 0x0000;R1= 0x0000;[P_IOA_Data] = R1;[P_IOA_Data] = R1;RETF;RETF;.ENDP.ENDP

//=============================//=============================//// 函数函数 : LightOff(): LightOff()//// 语法:语法: void LightOffvoid LightOff(( voidvoid ))//// 描述:熄灭描述:熄灭 ledled//// 参数:无参数:无//// 返回:无返回:无//=============================//=============================.PUBLIC _LightOff; //IOA.PUBLIC _LightOff; //IOA 口口 LEDLED熄灭熄灭_LightOff: .PROC_LightOff: .PROCR1= 0x0000;R1= 0x0000;[P_IOA_Data] = R1;[P_IOA_Data] = R1;RETF;RETF;.ENDP.ENDP

//==========================//==========================//// 函数函数 : LightOn(): LightOn()//// 语法:语法: void LightOnvoid LightOn (( voidvoid ))//// 描述:点亮描述:点亮 ledled//// 参数:无参数:无//// 返回:无返回:无//==========================//==========================.PUBLIC _LightOn; //IOA.PUBLIC _LightOn; //IOA 口口 LEDLED 点亮点亮_LightOn: .PROC_LightOn: .PROCR1= 0xFFFF;R1= 0xFFFF;[P_IOA_Data] = R1;[P_IOA_Data] = R1;RETF;RETF;.ENDP.ENDP

//==========================//==========================//// 函数函数 : LightOn(): LightOn()//// 语法:语法: void LightOnvoid LightOn (( voidvoid ))//// 描述:点亮描述:点亮 ledled//// 参数:无参数:无//// 返回:无返回:无//==========================//==========================.PUBLIC _LightOn; //IOA.PUBLIC _LightOn; //IOA 口口 LEDLED 点亮点亮_LightOn: .PROC_LightOn: .PROCR1= 0xFFFF;R1= 0xFFFF;[P_IOA_Data] = R1;[P_IOA_Data] = R1;RETF;RETF;.ENDP.ENDP

_IRQ5:_IRQ5:PUSH R1,R5 TO [SP]PUSH R1,R5 TO [SP]R1 = 0x0008;R1 = 0x0008;TEST R1,[P_INT_Ctrl];TEST R1,[P_INT_Ctrl];JNZ JNZ L_IRQ5_4HzL_IRQ5_4Hz;;L_IRQ5_2Hz:L_IRQ5_2Hz: //2Hz //2Hz 中断中断R1=0x0004R1=0x0004[P_INT_Clear] = R1; //[P_INT_Clear] = R1; // 清中断清中断R1=[R1=[_TimeCount_TimeCount] //] // 计数器计数器 +1+1R1+=1R1+=1[[_TimeCount_TimeCount]=R1]=R1POP R1,R5 FROM [SP];POP R1,R5 FROM [SP];RETI;RETI;L_IRQ5_4HzL_IRQ5_4Hz: //4Hz: //4Hz 中断中断[P_INT_Clear] = R1;[P_INT_Clear] = R1;POP R1,R5 FROM [SP];POP R1,R5 FROM [SP];RETI;RETI;

_IRQ5:_IRQ5:PUSH R1,R5 TO [SP]PUSH R1,R5 TO [SP]R1 = 0x0008;R1 = 0x0008;TEST R1,[P_INT_Ctrl];TEST R1,[P_INT_Ctrl];JNZ JNZ L_IRQ5_4HzL_IRQ5_4Hz;;L_IRQ5_2Hz:L_IRQ5_2Hz: //2Hz //2Hz 中断中断R1=0x0004R1=0x0004[P_INT_Clear] = R1; //[P_INT_Clear] = R1; // 清中断清中断R1=[R1=[_TimeCount_TimeCount] //] // 计数器计数器 +1+1R1+=1R1+=1[[_TimeCount_TimeCount]=R1]=R1POP R1,R5 FROM [SP];POP R1,R5 FROM [SP];RETI;RETI;L_IRQ5_4HzL_IRQ5_4Hz: //4Hz: //4Hz 中断中断[P_INT_Clear] = R1;[P_INT_Clear] = R1;POP R1,R5 FROM [SP];POP R1,R5 FROM [SP];RETI;RETI;

////中断程序中断程序 ISR.ASMISR.ASM.PUBLIC _IRQ5.PUBLIC _IRQ5.INCLUDE hardware.inc.INCLUDE hardware.inc.EXTERNAL .EXTERNAL _TimeCount_TimeCount; //; // 计时计时.TEXT.TEXT//========================//========================//// 函数函数 : IRQ5(): IRQ5()//// 语法:语法: void IRQ5void IRQ5(( voidvoid ))//// 描述:描述: IRQ5IRQ5 中断服务程序中断服务程序//// 参数:无参数:无//// 返回:无返回:无//========================//========================

////中断程序中断程序 ISR.ASMISR.ASM.PUBLIC _IRQ5.PUBLIC _IRQ5.INCLUDE hardware.inc.INCLUDE hardware.inc.EXTERNAL .EXTERNAL _TimeCount_TimeCount; //; // 计时计时.TEXT.TEXT//========================//========================//// 函数函数 : IRQ5(): IRQ5()//// 语法:语法: void IRQ5void IRQ5(( voidvoid ))//// 描述:描述: IRQ5IRQ5 中断服务程序中断服务程序//// 参数:无参数:无//// 返回:无返回:无//========================//========================

?

Page 19: 第 4 章  程序设计

//**********************************///**********************************/// // 描述: 汇编调用描述: 汇编调用 CC 的函数的函数// // 日期: 日期: 2002/12/102002/12/10//**********************************///**********************************/.EXTERNAL _F_Sub_C.EXTERNAL _F_Sub_C.CODE.CODE.PUBLIC _main;.PUBLIC _main;//==================================//==================================// // 函数: 函数: main()main()// // 描述:主函数描述:主函数//==================================//==================================_main:_main:R1 = 1;R1 = 1;PUSH R1 TO [SP]; //PUSH R1 TO [SP]; // 第第 33 个参数入栈个参数入栈R1 = 2;R1 = 2;PUSH R1 TO [SP]; //PUSH R1 TO [SP]; // 第第 22 个参数入栈个参数入栈R1 = 3;R1 = 3;PUSH R1 TO [SP]; //PUSH R1 TO [SP]; // 第第 11 个参数入栈个参数入栈CALL _F_Sub_C;CALL _F_Sub_C;POP R1,R3 FROM [SP]; //POP R1,R3 FROM [SP]; //弹出参数回复弹出参数回复 SPSP 指针指针GOTO GOTO _main_main;;RETF;RETF;

//**********************************///**********************************/// // 描述: 汇编调用描述: 汇编调用 CC 的函数的函数// // 日期: 日期: 2002/12/102002/12/10//**********************************///**********************************/.EXTERNAL _F_Sub_C.EXTERNAL _F_Sub_C.CODE.CODE.PUBLIC _main;.PUBLIC _main;//==================================//==================================// // 函数: 函数: main()main()// // 描述:主函数描述:主函数//==================================//==================================_main:_main:R1 = 1;R1 = 1;PUSH R1 TO [SP]; //PUSH R1 TO [SP]; // 第第 33 个参数入栈个参数入栈R1 = 2;R1 = 2;PUSH R1 TO [SP]; //PUSH R1 TO [SP]; // 第第 22 个参数入栈个参数入栈R1 = 3;R1 = 3;PUSH R1 TO [SP]; //PUSH R1 TO [SP]; // 第第 11 个参数入栈个参数入栈CALL _F_Sub_C;CALL _F_Sub_C;POP R1,R3 FROM [SP]; //POP R1,R3 FROM [SP]; //弹出参数回复弹出参数回复 SPSP 指针指针GOTO GOTO _main_main;;RETF;RETF;

//==================================//==========================================//// 函数函数 : F_Sub_C(): F_Sub_C()//// 语法:语法: void F_Sub_C(int i,int j,int k)void F_Sub_C(int i,int j,int k)//// 描述:延时程序描述:延时程序//// 参数:参数: i,j,ki,j,k//// 返回:返回: ii//==================================//==========================================int F_Sub_C(int i,int j,int k)int F_Sub_C(int i,int j,int k)//i=3//i=3 ,, j=2j=2 ,, k=1k=1 。。{{

i++;i++;j++;j++;k++;k++;return i;return i;

}}

//==================================//==========================================//// 函数函数 : F_Sub_C(): F_Sub_C()//// 语法:语法: void F_Sub_C(int i,int j,int k)void F_Sub_C(int i,int j,int k)//// 描述:延时程序描述:延时程序//// 参数:参数: i,j,ki,j,k//// 返回:返回: ii//==================================//==========================================int F_Sub_C(int i,int j,int k)int F_Sub_C(int i,int j,int k)//i=3//i=3 ,, j=2j=2 ,, k=1k=1 。。{{

i++;i++;j++;j++;k++;k++;return i;return i;

}} 汇编语言程序汇编语言程序调用调用 CC 函数函数

汇编语言程序汇编语言程序调用调用 CC 函数函数

例【 4.13 】

返回值还在吗返回值还在吗 ??返回值还在吗返回值还在吗 ??

增加指令:增加指令: R4=R1R4=R1增加指令:增加指令: R4=R1R4=R1

修改指令:修改指令: POP R2POP R2 ,, R4 FROM R4 FROM [[ SPSP]]只有一个空闲寄存器只有一个空闲寄存器 ,, 比如比如 R4:R4: POP R4 FROM POP R4 FROM [[ SPSP]] POP R4 FROM POP R4 FROM [[ SPSP]] POP R4 FROM POP R4 FROM [[ SPSP]]

修改指令:修改指令: POP R2POP R2 ,, R4 FROM R4 FROM [[ SPSP]]只有一个空闲寄存器只有一个空闲寄存器 ,, 比如比如 R4:R4: POP R4 FROM POP R4 FROM [[ SPSP]] POP R4 FROM POP R4 FROM [[ SPSP]] POP R4 FROM POP R4 FROM [[ SPSP]]

Page 20: 第 4 章  程序设计

作业作业

P129 P129 33 、、 44 、、 88

P129 P129 33 、、 44 、、 88

Page 21: 第 4 章  程序设计

程序设计程序设计 -I/O-I/O端口初始化,端口初始化,数字计算与处理。数字计算与处理。

汇编语言程序设计汇编语言程序设计CC 与汇编交叉调用与汇编交叉调用

阅读程序阅读程序

本章小节本章小节

Page 22: 第 4 章  程序设计

§4.3.1C§4.3.1C 语言的在线汇语言的在线汇编编

指令格式指令格式 asm (asm (““ 汇编指令模板”:输出参数:输入参数:汇编指令模板”:输出参数:输入参数: clobbersclobbers 参数参数 ));;

例、 例、 asm (asm (“%0+=%1”“%0+=%1” :“:“ +r”+r”(( foofoo ):“):“ r”r”(( barbar)) ));;

汇编指令摸板汇编指令摸板说明当前汇编指令。如, 说明当前汇编指令。如, ““ %0+=%1”%0+=%1” ::其中其中%0%0 、 、 %1%1 为形参,数字为冒号后操作数序号。将为形参,数字为冒号后操作数序号。将分别被输入输出参数替代。分别被输入输出参数替代。

操作数—上例中, 操作数—上例中, (( foofoo )、 ()、 ( barbar))约束符—上例中, 约束符—上例中, ““ +r” +r” 、“、“ r”r”

约束符约束符 操作数存储类型操作数存储类型 约束符前缀及含义解释约束符前缀及含义解释rr 寄存器中的数值寄存器中的数值 == ++

mm 存储器内的数值存储器内的数值为操作数赋值为操作数赋值

操作数在被赋操作数在被赋值前先要参加值前先要参加运算运算

ii 立即数立即数pp 全局变量操作全局变量操作

Page 23: 第 4 章  程序设计

[[ 例例 4.7]4.7] 、 、 asmasm (”(”%0=%0=%1%1++%2%2”” :”:” =r”=r” (( foofoo ):):”” r”r” (( barbar ),”),”i”i” (( 1010 ))););

汇编代码:汇编代码: R1=R1=R4R4++1010[[ 例例 4.8]4.8] 、 、 asm(“.include hareware.inc”);asm(“.include hareware.inc”); // // 要使用端口名时,打开此要使用端口名时,打开此文件。文件。

asmasm ((““ [P_IOB_Attrib]=[P_IOB_Attrib]=%0\n\t%0\n\t”” ““[P_IOB_Data]=[P_IOB_Data]=%1\n\t%1\n\t” ” ““[P_IOB_Dir]=[P_IOB_Dir]=%0\n\t%0\n\t”” :: :: ““r”r” (( 00 )),, ““r”r” (( 0xffff0xffff )) );); ////初始化初始化 BB 口为带上拉电阻的输入。口为带上拉电阻的输入。[[ 例例 4.9]4.9] 、……、……

int tempint temp ;;asm (“.include hareware.inc”);asm (“.include hareware.inc”); asmasm ((““ %0= [P_IOB_Data]”%0= [P_IOB_Data]” : : ““ =r”=r” (( temptemp )); ));

asmasm ( ( ““ [P_IOA_Buffer]=%0”[P_IOA_Buffer]=%0” ::: : ““ r” r” (( temptemp )); )); 将将 BB 口的数据 口的数据 temptemp ; ; temp temp A A 口输出。口输出。

在线汇编举例在线汇编举例

一个指令模板挂接多一个指令模板挂接多条汇编指令时,用条汇编指令时,用 \N\N 结结束每条指令。用束每条指令。用 \t\t 来对齐来对齐模板中的各指令。模板中的各指令。

一个指令模板挂接多一个指令模板挂接多条汇编指令时,用条汇编指令时,用 \N\N 结结束每条指令。用束每条指令。用 \t\t 来对齐来对齐模板中的各指令。模板中的各指令。

没有输出参数。没有输出参数。 没有输出参数。没有输出参数。

Page 24: 第 4 章  程序设计

EXTERNAL EXTERNAL _addsum_addsum.CODE.CODE.public _main.public _main_main:_main: r1=0x55 //r1=0x55 // 第第 11 个参数个参数 r2=0x20 //r2=0x20 // 第第 22 个参数个参数 push r1,r2 to [sp]push r1,r2 to [sp] call call _addsum_addsum r3=r1 //r3=r1 // 返回值返回值 pop r1,r2 from [sp] pop r1,r2 from [sp] loop:loop: r1=0r1=0 jmp loopjmp loop

EXTERNAL EXTERNAL _addsum_addsum.CODE.CODE.public _main.public _main_main:_main: r1=0x55 //r1=0x55 // 第第 11 个参数个参数 r2=0x20 //r2=0x20 // 第第 22 个参数个参数 push r1,r2 to [sp]push r1,r2 to [sp] call call _addsum_addsum r3=r1 //r3=r1 // 返回值返回值 pop r1,r2 from [sp] pop r1,r2 from [sp] loop:loop: r1=0r1=0 jmp loopjmp loop

int int addnumaddnum(int m,int n)(int m,int n) //// 第第 11 个参数送个参数送 mm ,第,第 22 个参数个参数送送 nn 。。{{ int j=0;int j=0; int i=0;int i=0; for (i=1; i<=m; i++)for (i=1; i<=m; i++) j=j+n;j=j+n; return(j)return(j)}}

int int addnumaddnum(int m,int n)(int m,int n) //// 第第 11 个参数送个参数送 mm ,第,第 22 个参数个参数送送 nn 。。{{ int j=0;int j=0; int i=0;int i=0; for (i=1; i<=m; i++)for (i=1; i<=m; i++) j=j+n;j=j+n; return(j)return(j)}}

PCPC

SRSR

0x550x55

0x200x20

调用前调用前 SSPP

调用后调用后 SSPP

第第 11 个参数个参数第第 22 个参数个参数

在汇编函数中要调用在汇编函数中要调用 CC 语言的子语言的子函数,应该根据函数,应该根据 CC 的函数原型所要的函数原型所要求的参数类型,分别把参数压入堆求的参数类型,分别把参数压入堆栈后,再调用栈后,再调用 CC 函数。调用结束返函数。调用结束返回后还需再进行出栈操作,以恢复回后还需再进行出栈操作,以恢复调用调用 CC 函数前的堆栈指针。函数前的堆栈指针。

在汇编函数中要调用在汇编函数中要调用 CC 语言的子语言的子函数,应该根据函数,应该根据 CC 的函数原型所要的函数原型所要求的参数类型,分别把参数压入堆求的参数类型,分别把参数压入堆栈后,再调用栈后,再调用 CC 函数。调用结束返函数。调用结束返回后还需再进行出栈操作,以恢复回后还需再进行出栈操作,以恢复调用调用 CC 函数前的堆栈指针。函数前的堆栈指针。

???? 弹出已不用参弹出已不用参数,清理堆栈垃圾,数,清理堆栈垃圾,恢复指针。恢复指针。

弹出已不用参弹出已不用参数,清理堆栈垃圾,数,清理堆栈垃圾,恢复指针。恢复指针。

汇编程序调用汇编程序调用 CC 语语言言

汇编程序调用汇编程序调用 CC 语语言言