Linux操作系统Lab1

实验要求

将一个简单的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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值