计算机是怎样工作的-函数调用堆栈机制

简介:解释单任务计算机(不考虑中断)的函数调用堆栈机制,并在此基础上讨论分析多任务计算机是怎样工作的

实验过程:

从c源代码到运行可执行程序一般要经过以下几个阶段:

预处理->编译->汇编->链接

源程序:example.c 

int g(int x){
    return x+3;
}

int f(int x){
    return g(x);
}

int main(void){
    return f(8)+1;
}

 1.预处理:将c源文件预处理生成example.cpp文件

 2.编译:将预处理好的example.cpp文件编译生成example.s汇编代码 

3.汇编:将汇编代码example.s文件编译为目标文件example.o

4.链接:将目标文件example.o与所需的所有附加的目标文件连接起来,生成可执行文件example(本实验未包含静态和动态链接库这样的附加的目标文件)

 实验分析:

查看example.s文件,分析main()函数的执行过程:

  伪代码:

g:
.LFB0:    
    pushl    %ebp    
    movl    %esp, %ebp    
    movl    8(%ebp), %eax
    addl    $3, %eax
    popl    %ebp    
    ret

f:
.LFB1:    
    pushl    %ebp    
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    g
    leave    
    ret


main:
.LFB2:    
    pushl    %ebp    
    movl    %esp, %ebp    
    subl    $4, %esp
    movl    $8, (%esp)
    call    f
    addl    $1, %eax
    leave    
    ret
    

在main函数段的部分,首先构造堆栈框架

 pushl    %ebp    
 movl    %esp, %ebp 

                        堆栈变化


 接着将要调用的函数参数压栈

subl    $4, %esp
movl    $8, (%esp)

        堆栈变化


 然后调用函数f()

	call	f

 

        堆栈的变化    

 

                         程序代码段的变化


f()函数段部分,类似的构建堆栈

pushl    %ebp     
movl
%esp, %ebp subl $4, %esp

                    堆栈变化


 接着,将参数8存入寄存器eax,并将该值存入esp所指向的内存单元

movl    8(%ebp), %eax
movl    %eax, (%esp)

      堆栈变化


然后调用g()函数

	call	g

     

            堆栈变化                   程序代码段变化


函数g()部分,类似的构造堆栈,将参数8存储到eax,执行加3运算后在存入eax作为函数的返回值,最后将ebp出栈,返回到f()

pushl    %ebp    
movl    %esp, %ebp    
movl    8(%ebp), %eax
addl    $3, %eax
popl %ebp
ret

堆栈变化:      构造堆栈                  ebp出栈                  执行ret 弹出地址

  

    程序代码段变化


返回到f()段后,执行将栈返回并返回main()函数

leave    
ret

            

堆栈变化: 执行leave后            执行ret后                    程序代码段变化


 回到main()函数段后,执行将eax中的值11执行加1运算后存入eax作为main()函数的返回值,接着将栈返回并退出

      堆栈返回

实验总结:

  对于单任务计算机,通过eip找到程序代码段顺序执行每一条指令,当遇到控制语句(如跳转指令jmp)以及过程调用(如本实验中的call g)时会改变eip的值,使eip跳转到不同的位置继续顺序的执行程序代码段的每一条指令。不同的函数具有不同的栈空间,当执行有关堆栈操作的指令时(如本实验中的push等),相应函数的堆栈会发生相应的变化。

  对于多任务计算机,通常利用时间片轮转的机制,系统的调度进程转依次调度执行就绪队列中进程。每个进程都有自己独立的进程空间,所以在进程切换时,会首先进行进程上下文切换,接着就如同单任务计算机一样执行当前的进程

 

 

 

  

 

 

posted @ 2013-05-16 21:27 Firewalls 阅读(...) 评论(...) 编辑 收藏