请教:活动记录

发布于 2022-09-18 18:22:13 字数 1467 浏览 17 评论 0

最近看虎书,对“活动记录”一章有以下疑问:
1、在 Frame.h, Frame.c 中,要实现 F_newFrame(), F_allocLocal() , InFrame(), InReg() 这几个函数功能的话,首先要确定 frame 的结构。按照书上对 frame 的描述为:{局部变量列表,返回地址,临时变量列表,实参列表,静态链,函数名字(frame名字),*fp,*sp}。但是书上只是提到在 F_newframe 的时候只需要2个参数(即 Temp_label name 和 F_accessList formals)。本人倾向于将frame的结构定为:{局部变量列表,返回地址,临时变量列表,实参列表,静态链,函数名字(frame名字),*fp,*sp}。不知道各位有何看法?

2、接着上面的问题,对于frame的结构定为:{局部变量列表,返回地址,临时变量列表,实参列表,静态链,函数名字(frame名字),*fp,*sp},我们需要为frame的元素分配内存空间(假设都是逃逸的)吗?这个问题似乎没必要问,活动记录里面存放的就是函数里各种数据的信息,不分配空间怎么行!但是,前一章里面,我已建立了符号表,并且已将相关符号的名字和类型信息存入符号表,而且符号表是已分配内存空间了的。那是不是说frame管的就是“变量的值”,而符号表管的是“变量/函数的类型,作用域”等这些信息呢?如果是的话,frame和符号表之间如何交叉?是通过变量名字/函数名字吗?如果是的话,在使用 Temp_newlabel() (在 temp.c )为变量和函数另外取名的,该如何对应?(Temp_newlabel()并不是像散列函数一样通过算法得出新的名字的)。

3、有关 *fp , *sp。 按书上描述, 当函数 g() 调用 函数 f(), 栈指针首先指向 f() 的第一个参数(这时处于函数 g()的frame中),然后进入函数f(),"当前 fp" = sp , "当前 sp" = fp - 函数f() 的 frame长度。我的理解是:在未进入函数体之前(即“当函数 g() 调用 函数 f(), 栈指针首先指向 f() 的第一个参数(这时处于函数 g()的frame中)),在 函数声明 匹配后(即 semant.c 中的transDec中 case A_functiondec 匹配),就可以进行 F_newframe , 而每个函数体里用到的变量会在 transDec 中 case A_vardec 匹配,即匹配变量声明后再记录入frame。如果以上我的理解没错的话,那么 当调用 F_newframe 时 frame 的长度是未最终确定的。如果要等到frame长度确定的话,恐怕要在函数的出口处。也就是说,问题的焦点在:F_newframe时未能确定 *fp 和 *sp,也未能提供从 *fp开始的一片大小为(fp - sp)的空间,这使得frame中的成员没有数据存放的地方(空指针)!因此,我想请教:在什么时候设置 *fp, *sp ? 如何设置。

4、有关返回地址。对于汇编,我知道返回地址放在 CS:IP 中,但如何用C 去将 “汇编指令 CALL”的下一个动作 PUSH CS,PUSH IP 转成 C语言并将CS和IP放进frame中的返回地址处。当函数返回时又该如何做?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

握住你手 2022-09-25 18:22:13

先顶一下

情深如许 2022-09-25 18:22:13

void foo(char *s)
{
        printf("I'm foo()...%s\n", s);
}
int main()
{
        char *s = "hello";
        foo(s);
}
-----------------------------------------

相应的汇编码大致如下:

foo:
    push ebp
    mov ebp, esp
    push dword ptr [ebp+8]
    push $LC0
    call printf
    pop ebp
    ret

main:
    push ebp
    mov ebp, esp
    sub esp,4
    push dword ptr [ebp-4]
    call foo
    add esp,0x0c
    pop ebp
    ret
---------------------------------------------
   
用 c 来实现 call 指令的行为:

void _call((void(*)())fn)
{
     *++reg.esp = reg.cs;
     *++reg.esp = reg.eip;
     fn();
}

void do_main()
{
    *++reg.esp = reg.ebp;
    reg.ebp = reg.esp;

     reg.esp -- ;

    *(reg.ebp-1) = s;

    _call(foo);

}

偏闹i 2022-09-25 18:22:13

谢楼上。

实在看的太烦了,虎书里也太精简了。各位谁有 semant.c translate.c frame.c(到中间代码生成这章)的 source ? 有的话共享一下,谢谢。

趁微风不噪 2022-09-25 18:22:13

原帖由 sherf 于 2009-4-14 04:50 发表
谢楼上。

实在看的太烦了,虎书里也太精简了。各位谁有 semant.c translate.c frame.c(到中间代码生成这章)的 source ? 有的话共享一下,谢谢。

源代码。

眼眸里的快感 2022-09-25 18:22:13

别瞎翻译了,frame就是frame。
虎书是教科书,得老师给你讲,当然你智商高的话就可以自学了,比如我这样的智商,60

给不了的爱 2022-09-25 18:22:13

yhb04,谢谢。

睡美人的小仙女 2022-09-25 18:22:13

yhb04,

最近在调试,发现 let declist in exp 有些问题,识别不了多个表达式(declist),在改动tiger.grm之后,原来的错误没了,但是却出现了其他的错误。回头看你的文件包里,却没有发现你的tiger.grm,能把你的那个 tiger.grm 一并共享给我吗?谢谢。

你げ笑在眉眼 2022-09-25 18:22:13

原帖由 sherf 于 2009-4-18 04:22 发表
yhb04,

最近在调试,发现 let declist in exp 有些问题,识别不了多个表达式(declist),在改动tiger.grm之后,原来的错误没了,但是却出现了其他的错误。回头看你的文件包里,却没有发现你的tiger.grm,能 ...

tiger.grm是什么东东?难道是描述Tiger的语法的yacc文件?
文件包里的源代码应该是全的,描述语法的yacc文件是 myparser.y 。

献世佛 2022-09-25 18:22:13

yhb04,

看到了,对,就是myarser.y这个文件

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文