首页 > 代码库 > 用汇编来解释“计算机是怎么工作的”

用汇编来解释“计算机是怎么工作的”

本文章为《Linux内核分析》实验报告

梁永锐

原创作品转载请注明出处 http://www.cnblogs.com/liangyongrui/p/6392035.html 

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”

-----

以下为要分析的c代码

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

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

int main(void)
{
    return f(81) + 12;
}
gcc –S –o main.s main.c -m32

编译成32位汇编后(去了点开头的行

g:
    pushl    %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $36, %eax
    popl    %ebp
    ret
f:
    pushl    %ebp
    movl    %esp, %ebp
    pushl    8(%ebp)
    call    g
    addl    $4, %esp
    sall    $2, %eax
    leave
    ret
main:
    pushl    %ebp
    movl    %esp, %ebp
    pushl    $81
    call    f
    addl    $4, %esp
    addl    $12, %eax
    leave
    ret

一.实验截图:

技术分享

技术分享

技术分享

二. 汇编代码的工作过程中堆栈的变化

从main开始

pushl %ebp

movl %esp, %ebp

也就是enter指令(不知道为什么这里并没有把他写成enter而是分开写了)

 

这两条指令执行后我们假设,ebp,esp均为100(以下内容用ebp=100,  esp=100这种方法表示)

pushl $81

ebp=100, esp = 96,[96]=81([96]=81, 表示位置96的地方存了81这个数, 以下均用这种方法表示)

call f

ebp = 100, esp = 92, [92]= 22(这里用行号做eip)

跳到了f

pushl %ebp

ebp = 100, esp = 88, [88]=100

movl    %esp, %ebp

ebp = 88, esp = 88

pushl 8(%ebp)

ebp = 88, esp = 84, [84] = 81

call    g

ebp = 88, esp = 80, [80] = 13

 

然后调到了g函数

pushl    %ebp

ebp = 88, esp = 76, [76] = 88

movl    %esp, %ebp

ebp = 76, esp = 76

movl    8(%ebp), %eax

把传入的参数放在eax中, eax = 81

addl    $36, %eax

eax = 81 + 36 = 117

popl    %ebp

ebp = 88, esp = 80

ret

ebp = 88, esp = 84, eip = 13

此时就跳到13行了

addl    $4, %esp

弹出传入的参数,不赋值

ebp = 88, esp = 88

sall    $2, %eax

编译器很智能,乘4,自动变成了左移两位, eax = 117 << 2 = 468

leave

leave就是

movl %ebp, %esp  : ebp = 88, esp = 88

popl %ebp : ebp = 100, esp = 92

ret

ebp = 100, esp = 94, eip = 22

跳到第22行

addl    $4, %esp

弹出参数 

esp = 96

addl $12, %eax

eax = 468 + 12 = 480

leave
ret

回到main函数之前的堆栈和eip

 

三.计算机是如何工作的

简单的说,计算机就是按照ip一条条的执行指令,执行的时候需要一些寄存器做辅助,ip有时候也会跳。

 

用汇编来解释“计算机是怎么工作的”