通俗点讲
就是
程序运行完了,
还要保留
临时数据
和
运行状态,
等下一次
调用时
继续
执行
和普通程序的
区别:
普通程序(如一个
子函数)
调用完了
,
临时数据
就
不需要了,
分配的
内存
空间
就
回收了,
而
驻留程序
是
要保留这些的
驻留
程序
主要
用于
中断函数
,
非中断函数
也
有应用,较少。分别举个例子:
1)用于
中断:
假设
一个
用
做的
时钟函数,定时器
设置为
1s一个中断。
main()
{
显示
时间
hour,min,sec;
//
循环
刷屏显示
}
中断函数
{
sec++
if(sec>=60)
{
sec=0
min++
}
if(min>=60)
{
min=0
hour++
}
if(hour>=24)
{
hour=0
}
}
这时候
就能看出,
中断程序
在
运行完的
时候
不能
把
3个
变量
清空,
因为
下次
中断
还要用到
上次的
值,
这个程序
要
一直
驻留
内存;
2)再来个
普通
函数的
假设
做了一个程序
,程序中
有一个
函数aa,而
函数
aa
我只能
让它执行
3次就得
关闭程序(这个
用在
密码
验证上)
aa()
{
密码验证次数n+1
返回n
和
验证结果
}
那这个
aa函数
在
密码
验证
阶段
就要
常驻
内存
给你上个较完整的程序,可以直接在KEIL中运行并观察输出/******************************************************************************
功能:
本程序在12M晶振模式下,通过定时器中断精确实现数字时钟计时 *** 作,并在KEIL
中实现输出。时、分、秒的变化在定时中断里处理。
说明:
因采用工作方式2,自动装入初值,所以此程序计时很精确,只是在KEIL中模拟输
出显示的变化速度很快,这点可不理会
******************************************************************************/
#include
#include
#define
TEST
//此行用于KEIL输出显示,如果不需要显示可将其删除
typedef
unsigned
char
uchar
typedef
unsigned
int
uint
#define
TH0TL0_INIT
(256-250)
//定时器8位自动装入模式下寄存器初值,0.25ms中断一次
char
cHour
//时
char
cMin
//分
char
cSec
//秒
uint
iCount
//秒计数,计数达到4000时1s,4000*0.25ms
=1000ms
=
1s
bit
bSecChanged
//秒发生变化标志,每秒送一次输出显示,送显完成后清0,提高主程序效率
//==============================================================================
//T0定时器中断服务程序,12M晶振下每0.25ms产生中断,本程序执行一次
//==============================================================================
void
Timer0()
interrupt
1
{
iCount++
//秒计数值+1
if(iCount==4000)
{//时间计数达到1S
iCount
=
0
//重新开始下一秒计数
cSec++
//时钟:秒稿饥+1
bSecChanged
=
1
//置秒发生变化标志
if(cSec==60)
{//计够60s
cSec
=
0
//重新开始下一分计数
cMin++
//时钟:分+1
}
if(cMin==60)
{//计够60分钟
cMin
=
0
//重新开始下一小时计数
cHour++
//时钟:小时+1
}
if(cHour==24)
{//计够24小时
cHour
=
0
//重新开始第二键闭返天计数
}
}
}
//==============================================================================
//主程序
//==============================================================================
void
main()
{
uchar
outstr[10]
//输出字符串,我的编译器可能有问题,直接输出有态如错
TMOD
=
0X02//工作方式2,8位自动重装计时模式
TH0
=
TH0TL0_INIT
//0.25ms中断一次
TL0
=
TH0TL0_INIT
//0.25ms中断一次
#ifdef
TEST
SCON
=
0x50
/*
SCON:
mode
1,
8-bit
UART,
enable
rcvr
*/
TMOD
|=
0x20
/*
TMOD:
timer
1,
mode
2,
8-bit
reload
*/
TH1
=
221
/*
TH1:
reload
value
for
1200
baud
@
16MHz
*/
TR1
=
1
/*
TR1:
timer
1
run
*/
TI
=
1
/*
TI:
set
TI
to
send
first
char
of
UART
*/
#endif
cHour
=
0
//时
cMin
=
0
//分
cSec
=
0
//秒
iCount
=
0
//秒计数
bSecChanged
=
0
outstr[2]
=
':'
//时分分隔符
outstr[5]
=
':'
//分秒分隔符
outstr[8]
=
0
//字符串结束符
EA=1
//开总中断
ET0=1
//允许T0中断
TR0=1
//启动T0
while(1)
{
if(bSecChanged==1)
{//秒发生变化,将时间值转换为可显示字符串准备送显示
bSecChanged
=
0//清除标志,节省CPU资源
outstr[0]
=
cHour/10
+
0x30
//将秒转换为ASCII码
outstr[1]
=
cHour%10
+
0x30
outstr[3]
=
cMin/10
+
0x30
//将分转换为ASCII码
outstr[4]
=
cMin%10
+
0x30
outstr[6]
=
cSec/10
+
0x30
//将小时转换为ASCII码
outstr[7]
=
cSec%10
+
0x30
#ifdef
TEST
printf("
%s\r",outstr)
//在KEIL中显示时钟
#endif
}
}
}
DOS中断中断属于汇编层面的内容,可以用asm内联实现:
在windows visual c++下用__asm关世嫌并键字。
在gcc下用__asm__宏即可。
示例(vc):
#include <stdio.h>int main()
{
__asm int 3h
return 0
}
这样就可以在C里面写入汇编代码了。
__asm 关键字用于调用内联汇编程序,并且可在 C 或 C++ 语句合法时出现。 它不能单独出现。 必须后跟汇编指令、一组在大括号中的命令、或者至少一对空大括号。 术语 “__asm 块”在此处指任何命令或命令组,不管是否在大括号内。
如果不与大括号一起使用,则 __asm 关键字表示此行的其余部分是一条汇编语言语搜迹句。 如果与大括号一起使用,则该关键字表示大括号之间的每一行都是一条汇编语言语句。为了与早期版本兼容,_asm 是 __asm 的同义词。
由于 __asm 关键字是语句分隔符,因此您可以将程序集指令者辩放在同一行中。
在 Visual C++ 2005 之前,指令
__asm int 3
不会导致在使用 /clr 编译时生成本机代码;编译器会将该指令转换为 CLR 中断指令。
__asm int 3 现在将导致为函数生成本机代码。 如果您希望函数导致代码中出现断点,还希望将函数编译为 MSIL,请使用 __debugbreak。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)