qxp

欢迎来到qxp的秘密基地~

本人致力于研究运筹学优化问题、深度学习算法、c++后端开发,欢迎一同交流~


Linux操作系统内核Lab1

目录

实验1.1

实验要求

将一个简单的C程序汇编成LoongArch或RISC-V汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。

实验背景

gcc对c程序的编译分为四个步骤

  1. 预处理:对头文件、注释、宏等进行预处理,使用命令 gcc -E hello.c -o hello.i生成.i/.ii文件
  2. 编译:将经过预处理的文件生成汇编代码,使用命令gcc -S hello.i -o hello.s生成.s文件
  3. 汇编:将汇编代码转换位二进制文件,使用命令gcc -c hello.s -o hello.o生成.o文件
  4. 链接:将目标文件最终链接成可执行文件,使用命令gcc hello.o -o hello

实验过程

本次实验中使用的c程序为:

#include <stdio.h>

int add_a_and_b(int a, int b) {
   return a + b;
}
int sub_a_and_b(int a,int b){
    return a-b;
}
int main() {
   return sub_a_and_b(add_a_and_b(2, 3),1);

最终生成的汇编代码及解读如下:

    .file   "lab1.c"
    .text
    .globl  add_a_and_b
    .type   add_a_and_b, @function
add_a_and_b:
.LFB0:
    .cfi_startproc
    pushq   %rbp    // rbp入栈保存当前待执行的指令,下面开始执行当前函数体中的指令
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp  // rbp = rsp,生成新的堆栈空间,rsp是64位
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)  // edi直接寻址、rbp间接寻址,将edi的值存入rbp中保存的地址-4后所指向的内存,32位
    movl    %esi, -8(%rbp)  // esi直接寻址、rbp间接寻址,将esi的值存入rbp中保存的地址-8后所指向的内存,32位
    movl    -8(%rbp), %eax  // rdp间接寻址、eax直接寻址,将rbp中保存的地址-8后所指向的值存入eax中,32位
    movl    -4(%rbp), %edx  // rbp间接寻址、edx直接寻址,将rbp中保存的地址-4后所指向的值存入edx中,32位
    addl    %edx, %eax  // eax = eax + edx
    popq    %rbp    // 将之前保存的栈顶值弹出,并赋给rbp
    .cfi_def_cfa 7, 8
    ret     // 函数指令执行完毕,返回并执行下一条指令
    .cfi_endproc
.LFE0:
    .size   add_a_and_b, .-add_a_and_b
    .globl  sub_a_and_b
    .type   sub_a_and_b, @function
sub_a_and_b:
.LFB1:
    .cfi_startproc
    pushq   %rbp    // rbp入栈保存当前待执行的指令,下面开始执行当前函数体中的指令
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp  // 直接寻址,将rsp中的值存入rbp中, 64位
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)  // edi直接寻址、rbp间接寻址,将edi的值存入rbp中保存的地址-4后所指向的内存,32位
    movl    %esi, -8(%rbp)  // esi直接寻址、rbp间接寻址,将esi的值存入rbp中保存的地址-8后所指向的内存,32位
    movl    -8(%rbp), %eax  // rdp间接寻址、eax直接寻址,将rbp中保存的地址-8后所指向的值存入eax中,32位
    movl    -4(%rbp), %edx  // rbp间接寻址、edx直接寻址,将rbp中保存的地址-4后所指向的值存入edx中,32位
    subl    %eax, %edx  // edx = edx - eax
    movl    %edx, %eax  // 直接寻址,将edx的值赋给eax
    popq    %rbp    // 将之前保存的栈顶值弹出,并赋给rbp
    .cfi_def_cfa 7, 8   
    ret     // 函数指令执行完毕,返回并执行下一条指令
    .cfi_endproc
.LFE1:
    .size   sub_a_and_b, .-sub_a_and_b
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    pushq   %rbp    // rbp入栈保存当前待执行的指令,下面开始执行当前函数体中的指令
    .cfi_def_cfa_offset 16  
    .cfi_offset 6, -16
    movq    %rsp, %rbp  // 直接寻址,将rsp的值存入rbp中
    .cfi_def_cfa_register 6
    movl    $3, %esi    // 立即寻址,将3存入esi中
    movl    $2, %edi    // 立即寻址, 将2存入edi中
    call    add_a_and_b     // 调用add_a_and_b函数,此时eax中保存了add_a_and_b(3,2)计算得到的值
    movl    $1, %esi    // 立即寻址,将1存入esi中
    movl    %eax, %edi      // 直接寻址,将eax中的值存入edi中
    call    sub_a_and_b     // 调用sub_a_and_b函数,此时eax中保存了最终计算得到的值
    popq    %rbp        // 将栈顶元素出栈并存入rbp中
    .cfi_def_cfa 7, 8
    ret     // 返回,退出main
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
    .section    .note.GNU-stack,"",@progbits

实验1.2

实验要求

构造一个Linux系统并跟踪分析Linux内核启动过程

调试

本次实验搭建在腾讯云上,使用vscode通过ssh远程连接完成实验,使用xshell辅助执行mykernel的启动,使用xmanager查看可视化页面

配置好环境后,使用命令 qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz启动Linux内核,Linux正常启动

退出程序,再使用qemu-system-x86_64 -kernel linux-5.4.34/arch/x86/boot/bzImage -initrd rootfs.cpio.gz -S -s进行debug状态,程序一启动就会马上暂停

使用vscode远程连接,使用命令gdb vmlinux进入gdb调试模式,执行命令b start_kernel在内核开始处打断点,程序运行到断点就会自动中断

使用list查看断点处的上下文

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦