2023-2024-1 20232808《Linux内核原理与分析》第二周作业

1、创建文件

连接主机...
连接主机成功
Last failed login: Sun Sep 24 11:07:55 CST 2023 from 218.92.0.93 on ssh:notty
There were 52583 failed login attempts since the last successful login.
Last login: Thu Sep 14 20:21:45 2023 from 123.127.3.78
[root@VM-8-6-centos ~]# cd /weilin/linux
-bash: cd: /weilin/linux: 没有那个文件或目录
[root@VM-8-6-centos ~]# cd /weilin/Linux
[root@VM-8-6-centos Linux]# vim main.c

检查main.c文件
在这里插入图片描述

2、汇编

使用 gcc -S.c文件编译成汇编文件.s

[root@VM-8-6-centos Linux]# gcc -S main.c -o main.s
[root@VM-8-6-centos Linux]# cat main.s
        .file   "main.c"
        .text
        .globl  g
        .type   g, @function
g:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $3, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   g, .-g
        .globl  f
        .type   f, @function
f:
.LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $8, %rsp
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, %edi
        call    g
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   f, .-f
        .globl  main
        .type   main, @function
main:
.LFB2:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $8, %edi
        call    f
        addl    $1, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE2:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)"
        .section        .note.GNU-stack,"",@progbits
[root@VM-8-6-centos Linux]# 

可以看到main.s中有多行以.开头的代码
这里使用sed命令删掉以.开头的行

sed -i '/[.]/d' main.s

3、删除多余代码

可以看到删除成功
在这里插入图片描述

4、分析

在这里插入图片描述
通过对比不难发现,汇编和C是一一对应的:g、f、main这三个函数一一对应。

g:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        addl    $3, %eax
        popq    %rbp
        ret
f:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $8, %rsp
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, %edi
        call    g
        leave
        ret
main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $8, %edi
        call    f
        addl    $1, %eax
        popq    %rbp
        ret

下面是具体分析:

  • 函数g:
    在栈上保存旧的基址(pushq %rbp)和设置新的基址(movq %rsp, %rbp),以便在函数结束时恢复栈的状态。
    将传入的参数edi存储到位于rbp-4的局部变量中(movl %edi, -4(%rbp))。
    从rbp-4处加载值到寄存器eax(movl -4(%rbp), %eax)。
    将寄存器eax中的值增加3(addl $3, %eax)。
    恢复栈的状态并返回(popq %rbp和ret)。
  • 函数f:
    在栈上保存旧的基址(pushq %rbp)和设置新的基址(movq %rsp, %rbp)。
    在栈上为局部变量分配空间(subq $8, %rsp)。
    将传入的参数edi存储到位于rbp-4的局部变量中(movl %edi, -4(%rbp))。
    从rbp-4处加载值到寄存器eax(movl -4(%rbp), %eax)。
    将寄存器eax中的值移动到寄存器edi中(movl %eax, %edi)。
    调用函数g(call g)。
    清理栈的空间(leave)并返回(ret)。
  • 函数main:
    在栈上保存旧的基址(pushq %rbp)和设置新的基址(movq %rsp, %rbp)。
    将值8存储到寄存器edi中,作为参数传递给函数f(movl $8, %edi)。
    调用函数f(call f)。
    将寄存器eax中的值增加1(addl $1, %eax)。
    恢复栈的状态并返回(popq %rbp和ret)。

5、Arm架构下的汇编结果

    .arch armv7-a
    .syntax unified

    .text
    .global g
g:
    push    {lr}
    add     r3, r0, #3
    mov     r0, r3
    pop     {pc}

    .global f
f:
    push    {lr}
    sub     sp, sp, #4
    str     r0, [sp]
    ldr     r0, [sp]
    bl      g
    add     sp, sp, #4
    pop     {pc}

    .global main
main:
    push    {lr}
    mov     r0, #8
    bl      f
    add     r0, r0, #1
    mov     r7, #1
    mov     r2, r0
    mov     r1, r7
    mov     r0, #4
    svc     0x00000000
    pop     {pc}

逐行分析代码

    .arch armv7-a
    .syntax unified

    .text
    .global g
g:
    push    {lr}        ; 将链接寄存器lr的值保存在栈上
    add     r3, r0, #3  ; 将r0寄存器的值加上3,结果存储在r3寄存器中
    mov     r0, r3      ; 将r3寄存器的值复制到r0寄存器中
    pop     {pc}        ; 从栈中恢复链接寄存器lr的值,然后跳转到lr寄存器所指示的地址

    .global f
f:
    push    {lr}        ; 将链接寄存器lr的值保存在栈上
    sub     sp, sp, #4  ; 将栈指针sp减去4个字节,为局部变量分配空间
    str     r0, [sp]    ; 将r0寄存器的值存储到栈内存中
    ldr     r0, [sp]    ; 从栈内存中加载值到r0寄存器中
    bl      g           ; 调用函数g(通过跳转并将返回地址保存在链接寄存器中)
    add     sp, sp, #4  ; 恢复栈指针sp的值,释放局部变量所占空间
    pop     {pc}        ; 从栈中恢复链接寄存器lr的值,然后跳转到lr寄存器所指示的地址

    .global main
main:
    push    {lr}        ; 将链接寄存器lr的值保存在栈上
    mov     r0, #8      ; 将8存储到r0寄存器中,作为参数传递给函数f
    bl      f           ; 调用函数f(通过跳转并将返回地址保存在链接寄存器中)
    add     r0, r0, #1  ; 将r0寄存器的值加上1
    mov     r7, #1      ; 将1存储到系统调用号寄存器r7中(表示退出程序)
    mov     r2, r0      ; 将r0寄存器的值复制到r2寄存器中
    mov     r1, r7      ; 将r7寄存器的值复制到r1寄存器中
    mov     r0, #4      ; 将4存储到r0寄存器中,表示系统调用号为4(write)
    svc     0x00000000  ; 触发系统调用,退出程序
    pop     {pc}        ; 从栈中恢复链接寄存器lr的值,然后跳转到lr寄存器所指示的地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值