易码技术论坛

 找回密码
 加入易码
搜索
12
返回列表 发新帖
楼主: gameghost

[教程] [原创][在LavaX中实现函数的越级返回]

[复制链接]
 楼主| 发表于 2006-10-5 17:06:09 | 显示全部楼层
那就请楼上这位权威认识认定一下吧~~~

(想到一个问题:不能再刷贴了,有可能被罚)
发表于 2006-10-5 17:11:16 | 显示全部楼层
算了,不说了
反正也不是用于医疗设备,出点问题没什么
发表于 2006-10-5 17:28:20 | 显示全部楼层
汗死。。。晕死。。。。
。。。。。。。。。。。。。。。。。。。。。。。
发表于 2006-10-5 17:58:20 | 显示全部楼层
据我所知,文曲星上LAVA解释器的实现中的RAM可以大致分为三个部分:
一个是基本运算(加,减,乘,除,赋值之类...)用到的一个栈,这个是最标准的栈了,四个字节一个单位,用push和pop操作.
还有一个是局部变量用到的栈,就是从$2000开始的那一块RAM了(可能是6K,20K,24K...大),程序运行时根据调用函数的实际情况来分配和吊销.在文曲星中LAVA的实行中,函数的返回地址也保存在其中。
不过我认为这一点不是一定的,完全可以用其它的实行方式把这个信息保存到其它地方去(比如专门建一个栈来保存函数的跳转和返回地址)。
还有一个是个循环队列,姑且称之为“池”吧,用来保存一些临时字符串数据.
比如:     printf("hello,world");就会先把"hello,world"这个字符串保存到“池”中去。
发表于 2006-10-5 18:04:38 | 显示全部楼层
这就是我说的双栈!
运算栈不做平衡的话会有问题!
发表于 2006-10-5 18:06:48 | 显示全部楼层
如果说是三个的话,就是:
运算栈
执行栈
字符串堆
发表于 2006-10-5 18:07:36 | 显示全部楼层
呵呵,对的...
刚刚看了下lz的代码,貌似里面的函数都是void的,所以不存在运算栈的平衡问题了。
but如果不是void的话...
发表于 2006-10-5 18:14:40 | 显示全部楼层
如果直接或间接调用一个有返回值的函数,而在此函数中远跳,运算栈就乱了!
 楼主| 发表于 2006-10-7 10:53:04 | 显示全部楼层
符一句,此返回和运算栈无关。
ForceReturn 的memcpy用来修改自己的返回属性,同时移动函数头到新的栈位置,changeram用来改变ForceReturn的开始内存,使堆栈异常出现在ForceReturn,在ForceReturn返回时堆栈异常随着返回而消失~
发表于 2006-10-7 11:02:53 | 显示全部楼层
不说了,都没理解什么是运算栈
发表于 2006-10-7 11:08:20 | 显示全部楼层
赫赫,还是用事实来说明吧:


long FileRetAdd;
int RamRetAdd;
int LastRam;
//相关函数*******************************
void SetReturn(long temp){
  //记录返回main函数的信息
  FileRetAdd = 0;
  memcpy(&FileRetAdd, temp - 5, 3);
  memcpy(&RamRetAdd, temp - 2, 2);
  LastRam = temp - 5;
}
void changeram(){
  int temp;
  //修改ReturnToMain的内存信息
  temp = LastRam;
  memcpy(&temp - 2, &temp, 2);
}
void ForceReturn(){
  long temp;
  //修改函数的返回信息
  memcpy(&temp - 5, &FileRetAdd, 3);
  memcpy(&temp - 2, &RamRetAdd, 2);
  memcpy(LastRam, &temp - 5,5);
  changeram();
}
//***************************************
void function1(){
  ForceReturn();//越级返回,如果去掉此行则以正常的方式返回
}
void function2(){
  function1();
  printf("return from function1!\n");
}
void function3(){
  function2();
  printf("return from function2!\n");
}
int function4(){
  char var;
  SetReturn(&var);//设定强制返回的地址为function4返回的地址.
  function3();
  printf("return from function3!\n");
  return 1;
}
int retadd(){//返回此函数的开始地址
  char add;
  return &add - 5;
}
void main()
{
  long temp;
  int x;
  SetScreen(1);
  temp = retadd();//存放现在的main函数的内存信息
  x =function4();
  printf("return from function4!\n");
  if(temp == retadd())//检测返回后的main的内存是否正常
   printf("main's ram is not changed!");
  getchar();
}


编译运行一下就知道鸟
发表于 2006-10-7 11:16:33 | 显示全部楼层
说一下:在调用SetReturn函数得那个函数如果有返回值就会出问题。
原因:碰到return语句时运算栈压栈,碰到var =function(...)时从运算栈弹出一个数。
lz的代码会导致跳过return语句没有压栈,但照样会pop,so...
发表于 2006-10-7 11:16:53 | 显示全部楼层
试了下,lvm报告:
错误的读写地址0-3
 楼主| 发表于 2006-10-8 14:36:38 | 显示全部楼层
变通一下就OK,function4要是int型就直接把ForceReturn也改成int型。
发表于 2006-10-8 14:55:43 | 显示全部楼层
要是float呢?
弄多个ForceReturn?
 楼主| 发表于 2006-10-8 15:12:42 | 显示全部楼层
这个~~~~~~恩,再弄个~~
 楼主| 发表于 2006-10-5 14:23:37 | 显示全部楼层 |阅读模式
/*
在多嵌套的程序中,如果在深层嵌套函数中遇到某些情况需要返回到主函数,
正常情况下需要一层一层的返回,这样就需要在每次返回后都要判断程序状态,
为了简化程序,可以通过修改内存来实现函数的越级返回,程序如下,
ForceReturn()函数就是用来直接返回的,之前要调用SetReturn记录返回地址.


如果一个函数调用SetReturn,那么强制返回函数ForceReturn返回的地方就是这个函数要返回的地方,
SetReturn的参数就是这个函数的第一个变量(如果有参数那么就是第一个参数)的地址,如:
fun(long para){
   SetReturn(
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-5-7 22:04 , Processed in 0.010639 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表