栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

2021-2022-1 20212802《Linux内核原理与分析》第二周作业

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021-2022-1 20212802《Linux内核原理与分析》第二周作业

本周的学习内容主要是庖丁解牛Linux的第一章,然后看完书后,又跟着云班课加深学习了一下第一章的内容。第一章主要讲述了linux里的汇编指令的一些指令,比如movl,pushl,popl等等,这些指令都是围绕数据结构中的栈做文章的。贯穿这一章的是esp、ebp,eip指针寄存器。简单来说,ebp就是指的栈底,esp就是指着栈顶。eip就是正在执行的指令所在的位置,然后不断重复的进行入栈出栈操作。

写了一个简单的C程序,如图所示,具体代码如下:

C语言代码:

    //mian.c    
    int g(int x)
    {
        return x + 3;
    }
     
    int f(int x)
    {
        return g(x);
    }
     
    int main(void)
    {
        return f(8) + 1;
    }

通过gcc -s -o main.s main.c -m32指令将其编译成汇编程序,打开该汇编文件并删除不重要的信息,如图所示,具体代码如下:

 反编译后汇编代码

    .file   "main.c"
    .text
    .globl  g
    .type   g, @function
g:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    movl    8(%ebp), %eax
    addl    $4, %eax
    popl    %ebp
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size   g, .-g
    .globl  f
    .type   f, @function
f:
.LFB1:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    g
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE1:
    .size   f, .-f
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $4, %esp
    movl    $6, (%esp)
    call    f
    addl    $2, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

 

我们来分析一下该汇编指令(通过画图的方式来帮助理解,为了区分不同时期的寄存器,将其后面加了个括号,括号里的数字表示该寄存器的第几种状态),如图所示:

 

首先执行main函数
pushl %ebp :将esp的值减4(指向下一帧栈地址),并将ebp寄存器里的值存入esp此时指向的栈地址。
Movl %esp, %ebp :将ebp寄存器同样指向esp寄存器指向的那块栈地址。
Sub $16, %esp :将esp寄存器的内容减16,即向下移动四个帧。
movl $1, -12(%ebp) : 将变址地址-12(%ebp)存入立即数1
movl $8, -8(%ebp) :将变址地址-8(%ebp)中存入立即数8
pushl -8(%ebp) : 将上述变址地址中的内容8压入栈内。
pushl -12(%ebp) :同样将上述变址地址中的内容1压入栈内。
call g : 即调用g子函数,可分为 pushl eip(存储call g的下一条指令即addl $8, %esp的地址)和 movl g, eip。
执行 g 子函数:
pushl %ebp : 将ebp的值压入栈内。
movl %esp, %ebp : 将ebp寄存器也指向esp所指示的位置。
movl 8(%ebp), %edx : 将8(%ebp)中的内容1存入edx寄存器中
movl 12(%ebp), %eax : 将12(%ebp)中的内容存入eax寄存器中
addl %edx, %eax : 将edx和eax中的内容相加并存入eax寄存器当中
popl %ebp : 将esp寄存器的内容加四,即向上移动一帧,将pop出的内容赋值给ebp, ebp指向之前ebp所指的位置
整个过程执行完后结果如新图所示:

 

ret : ret指令分为popl eip 和将eip寄存器存入保存的call指令的下条指令即 add.......
addl $8, %esp : 将esp寄存器向上移动两帧。
movl %eax, -4(%ebp) : 将eax的值9赋给-4(%ebp)的位置
movl -4(%ebp), %eax : 再从那个位置赋值给eax寄存器,(之所以那么绕,我认为是因为在C语言里我定义了一个变量c来得到g函数的返回值)
leave : 可分为 movl %ebp, %esp 和 popl ebp 即将esp指向ebp所指的位置,并将ebp以下的指令弹出,相当于清空栈。

 

总结:

1. 本周通过学习计算机汇编的基础知识和基本原理,理解到了计算机的基本原理存储程序和程序控制。

2. 预先要把指挥计算机如何进行操作的指令序列(称为程序)和原始数据通过输入设备输送到计算机内存贮器中。在书写或者解读汇编程序的时候,一定要关注每一条指令中规定的计算机取数的地址,进行了什么操作,然后送到什么地址去等步骤。如果只是单纯用眼睛去看,脑子去想肯定是不够的,汇编程序的重点就是在栈上做文章,一定要按过程画图来辅助自己的理解,这样一段程序的理解或者编写就会容易许多。

3. 本次实验的程序非常简单,但是重要的是要学会思考方式,为后面第三章程序的机器级表示的内容打好基础,把两章的内容结合起来去学习,学会用计算机的思维来进行思考和编程,会让我们对计算机系统的底层构造有更好的理解。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/292204.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号