为什么你的仿真机只占用2个字节的堆栈,而keil的 Mon51要用6个字节的堆栈? 答: 我的仿真机只需要使用用户的两个字节的堆栈,用户可以使用最多254字节的ram(52类单片机),而mon51仿真机需要使用6个字节的堆栈,用户最多可以使用250字节的ram,etool的51emb-32k也是占用6个字节的堆栈. keil mon51的堆栈占用分析: 仿真机是使用软件断点(跟专门的仿真机的硬件断点不同),是需要在用户程序的断点处写入一条 LCALL LF200H 指令(LF200H是监控程序的入口),(keil 的说明是有错误的,keil的说明是在断点处写入一条ACALL指令,我们知道ACALL指令的跳转范围是2k,而不是64K,如果是写入ACALL指令,那么用户程序最大不能超过2k).keil mon51的代码空间使用ram来存储的,用户代码可以被改写,我的仿真机是用SST89C58,SST89C58可以在运行中修改代码空间,改写用户代码),可以将位于断点处的用户代码改为LCALL监控程序代码.用户程序运行到断点处时,将执行一条LCALL指令跳到监控系统.举个例子:
上面是一个例子,要在0005处设置断点,0005处原来的代码为7401,是一条MOV指令, 监控系统将会修改0005处的代码,将0005-0006处的代码改为12F1 ,是一条LCALL指令,这里将 LCALL 0F1F6H .而监控程序的入口是0F100H-0F200H,0F1F6H落入监控程序入口.(根据用户install的参数不同,监控程序的入口不一样),0F100-0F200是我的仿真机的监控程序入口. KEIL 的监控程序:
一条LCALL 指令要入栈2个字节.一条PUSH指令要入栈1个字节,Keil的MON51使用了两条LCALL指令:LCALL 0F1XXH ; LCALL WRITEBYTE 需要占用4个字节的堆栈,使用了两个PUSH指令,占用2个字节的堆栈,共要占用6个字节的用户堆栈.如果用户可用堆栈少于6个字节,系统将会出错.
我的监控程序:
我的监控程序的执行过程没有使用PUSH指令,也没有使用LCALL指令,只有断点处的LCALL 0F1XXH 占用2个字节的堆栈. SFCF,SFAH,SFAL 等是SST89C58的特殊寄存器,用于运行过程中修改代码. 除了对监控程序的入口(从用户程序返回监控程序)做了很大的改动之外,对监控程序的出口(从监控程序返回用户程序)作相应的改动.以实现2字节的堆栈占用.对运行中用中断停止的代码也做了类似的修改. 2字节的堆栈占用是我的独创.etool使用的代码跟keil提供的代码差不多,同样占用6个字节的堆栈. |