C51调用嵌入汇编程序运行到RET总是返回到程序开始执行,子程序为清51RAM程序。
本人有两个源程序文件:1,“main.c”如下:#include"ClrRam.h"#include"MC96F7616A.h"voidmain(void){chari,...
本人有两个源程序文件:
1,“main.c” 如下:
#include "ClrRam.h"
#include "MC96F7616A.h"
void main(void)
{
char i,j;
IE &= ~0x80;
port_init();
ClrAllRam();//现在的问题是调用了这个子程序后,直接又从第一句开始运行了。
i = 0xf1;
j = 0xdf;
do
{
i = i*2+j;
} while (1);
}
2,“ClrAllRam.c” 如下:
#include "ClrRam.h"
#include "MC96F7616A.h"
void ClrAllRam(void)
{
#pragma ASM
MOV R0,#255
CLR A
IDATA_LOOP: MOV @R0,A
DJNZ R0,IDATA_LOOP
MOV DPTR,#0
MOV R7,#255
CLR A
XDATA_LOOP: MOVX @DPTR,A
INC DPTR
DJNZ R7,XDATA_LOOP
#pragma ENDASM
}
void port_init(void)
{
P0IO = 0xFF; // direction
P0PU = 0x00; // pullup
P0OD = 0x00; // open drain
P0DB = 0x00; // debounce : P93, 30, 01, 00
P0 = 0x00; // port initial value
P1IO = 0xFF; // direction
P1PU = 0x00; // pullup
P1OD = 0x00; // open drain
P1DB = 0x00; // debounce : P17 ~ P10
P1 = 0x00; // port initial value
P2IO = 0xFF; // direction
P2PU = 0x00; // pullup
P2OD = 0x00; // open drain
P2 = 0x00; // port initial value
P3IO = 0xFF; // direction
P3PU = 0x00; // pullup
P3OD = 0x00; // open drain
P3 = 0x00; // port initial value
P4IO = 0xFF; // direction
}
注:1,ClrAllRam();//现在的问题是调用了这个子程序后,直接又从第一句开始运行了。
2,"ClrAllRam.c" 文件有勾选generate assembler SRC file和assemble SRC file选项。 展开
1,“main.c” 如下:
#include "ClrRam.h"
#include "MC96F7616A.h"
void main(void)
{
char i,j;
IE &= ~0x80;
port_init();
ClrAllRam();//现在的问题是调用了这个子程序后,直接又从第一句开始运行了。
i = 0xf1;
j = 0xdf;
do
{
i = i*2+j;
} while (1);
}
2,“ClrAllRam.c” 如下:
#include "ClrRam.h"
#include "MC96F7616A.h"
void ClrAllRam(void)
{
#pragma ASM
MOV R0,#255
CLR A
IDATA_LOOP: MOV @R0,A
DJNZ R0,IDATA_LOOP
MOV DPTR,#0
MOV R7,#255
CLR A
XDATA_LOOP: MOVX @DPTR,A
INC DPTR
DJNZ R7,XDATA_LOOP
#pragma ENDASM
}
void port_init(void)
{
P0IO = 0xFF; // direction
P0PU = 0x00; // pullup
P0OD = 0x00; // open drain
P0DB = 0x00; // debounce : P93, 30, 01, 00
P0 = 0x00; // port initial value
P1IO = 0xFF; // direction
P1PU = 0x00; // pullup
P1OD = 0x00; // open drain
P1DB = 0x00; // debounce : P17 ~ P10
P1 = 0x00; // port initial value
P2IO = 0xFF; // direction
P2PU = 0x00; // pullup
P2OD = 0x00; // open drain
P2 = 0x00; // port initial value
P3IO = 0xFF; // direction
P3PU = 0x00; // pullup
P3OD = 0x00; // open drain
P3 = 0x00; // port initial value
P4IO = 0xFF; // direction
}
注:1,ClrAllRam();//现在的问题是调用了这个子程序后,直接又从第一句开始运行了。
2,"ClrAllRam.c" 文件有勾选generate assembler SRC file和assemble SRC file选项。 展开
1个回答
展开全部
这是牵扯C51单片机内部RAM多用问题,牵扯到寄存器R0---R7,堆栈区问题。
程序调用子程序时,把返回主程序时执行指令的地址存入堆栈内(内部RAM),堆栈地址由sp指定,如果你把内部RAM清零了,子程序返回时,返回地址就为0x0000H,即从新转入程序入口。
MOV R0,#255
CLR A
IDATA_LOOP: MOV @R0,A
DJNZ R0,IDATA_LOOP
就是这一段程序把返回地址清除为0x0000hH。
这段程序要谨慎使用,它会把寄存器R0----R7,的内容也同时清零了,
除非你知道寄存器和堆栈区地址在内部RAM哪两段区间;可以分段清零;
还有一种方法,把寄存器地址设置在00h--07h区间,进入该子程序时对返回地址进行保护,方法是
POP R1
POP R2
MOV R0,#255
MOV R3 ,#248 //注意00h---07h不清零,它已经指定寄存器区R0---R7
CLR A
IDATA_LOOP: MOV @R0,A
DEC R0
DJNZ R3,IDATA_LOOP
PUSH R2
PUSH R1
把返回地址存入R1,R2进行保护,操作完成再返还堆栈,至少内部00h,01h,02h,03h不清零
这只适用于主程序调用,如果出现子程序调用或者中断调用(程序嵌套)就要保护的多了,
最好的方法还是不对寄存器区和堆栈区清零。
我一般使用寄存器组区在内部RAM:00h---1fh,堆栈区在20h---3fh;小一点可以在20h---2fh
选择,系统默认寄存器为组0,00h---07h;堆栈区从08h开始,你可以不设置,选择默认,注意堆栈区上限。
程序调用子程序时,把返回主程序时执行指令的地址存入堆栈内(内部RAM),堆栈地址由sp指定,如果你把内部RAM清零了,子程序返回时,返回地址就为0x0000H,即从新转入程序入口。
MOV R0,#255
CLR A
IDATA_LOOP: MOV @R0,A
DJNZ R0,IDATA_LOOP
就是这一段程序把返回地址清除为0x0000hH。
这段程序要谨慎使用,它会把寄存器R0----R7,的内容也同时清零了,
除非你知道寄存器和堆栈区地址在内部RAM哪两段区间;可以分段清零;
还有一种方法,把寄存器地址设置在00h--07h区间,进入该子程序时对返回地址进行保护,方法是
POP R1
POP R2
MOV R0,#255
MOV R3 ,#248 //注意00h---07h不清零,它已经指定寄存器区R0---R7
CLR A
IDATA_LOOP: MOV @R0,A
DEC R0
DJNZ R3,IDATA_LOOP
PUSH R2
PUSH R1
把返回地址存入R1,R2进行保护,操作完成再返还堆栈,至少内部00h,01h,02h,03h不清零
这只适用于主程序调用,如果出现子程序调用或者中断调用(程序嵌套)就要保护的多了,
最好的方法还是不对寄存器区和堆栈区清零。
我一般使用寄存器组区在内部RAM:00h---1fh,堆栈区在20h---3fh;小一点可以在20h---2fh
选择,系统默认寄存器为组0,00h---07h;堆栈区从08h开始,你可以不设置,选择默认,注意堆栈区上限。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询