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

本文详细描述了X86和ARM汇编语言实验的过程,包括C语言编写、编译成汇编、代码分析和清理多余代码,旨在揭示计算机底层运行逻辑及其差异。学习者通过实际操作加深对计算机原理的理解。
摘要由CSDN通过智能技术生成

 

目录

 一、实验楼配套实验一(X86汇编语言)

1 、编写一个main.c函数

2、通过命令编译成可执行文件和汇编代码

3、打开main.s汇编代码进行查看

4、进行汇编代码的多余代码删除

5、进行汇编代码的分析

二、基于ARM的配套实验一(ARM汇编语言)

1、编写main.c函数

2、通过命令编译成汇编代码

3、查看汇编文件main.s

4、进行汇编代码的多余代码删除

5、进行汇编代码的分析

 三、总结

四、Chatgpt帮助


第二周作业内容:

1、阅读学习教材「庖丁解牛Linux 分析 」第1,2章

2、教材深入学习关注「Linux内核及安全」。

3、学习蓝墨云班课中第二周视频「计算机是如何工作的?」,并完成实验楼上配套实验一,基于树莓派或其他平台完成ARM相关内容。

4、完成蓝墨云班课中的测试。

 一、实验楼配套实验一(X86汇编语言)

        实验楼的环境是基于X86汇编语言的,下面还有一个基于ARM汇编语言的相同实验,我们可以进行比较学习,了解更多知识。

1 、编写一个main.c函数

2、通过命令编译成可执行文件和汇编代码

        通过以下代码,即可生成汇编代码,其中-m32指生成32位的汇编程序,再通过ls代码即可查看已经生成了main.s文件。

gcc –S –o main.s main.c -m32

3、打开main.s汇编代码进行查看

        通过以下代码即可查看main.s文件。

vi main.s

4、进行汇编代码的多余代码删除

        打开发现main.s代码比较凌乱,因此需要删除多余的辅助代码,而这些辅助代码就是类似“.size”等“.”开头的文件。通过以下代码即可删除所有“.”开头的辅助代码,且删除后的代码如下:

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

5、进行汇编代码的分析

        通过对比查看可发现,汇编代码和C语言代码其实是一一对应的。g、f、main和三个函数一一对应。

        下面进行代码分析:

g:                              
	pushl	%ebp                
	movl	%esp, %ebp          
	movl	8(%ebp), %eax       
	addl	$3, %eax            
	popl	%ebp                
	ret                         

f:                              
	pushl	%ebp                
	movl	%esp, %ebp          
	subl	$4, %esp            
	movl	8(%ebp), %eax      
	movl	%eax, (%esp)        
	call	g                   
	leave                       
	ret                         

main:                          
	pushl	%ebp               
	movl	%esp, %ebp         
	subl	$4, %esp            
	movl	$20232831, (%esp)  
	call	f                   
	addl	$1, %eax            
	leave                       
	ret                         

首先是进入main函数:

pushl %ebp                                    #将EBP(栈基值)寄存器的值压入栈中
movl %esp,%ebp                           #EBP指针指向标号1的位置
subl $4,%esp                                 #ESP指针向下增1,指向下一个标号位置
movl $20232831, (%esp)               #将立即数20232831放入ESP寄存器指向的标号2位置
call f                                               #调用g函数,先将ESP后移,存储现在EIP寄存器内的值,然后EBP内的值压榨存储到下一标号位置

call f即进入f函数,main函数的剩余部分等待执行 

pushl %ebp                                  #把ESP寄存器的值向下移到标号4
movl %esp, %ebp                        #把EBP寄存器的值标号1放到栈空间标号4的位置
subl $4,%esp                               #ESP寄存器指针向下加1,指向下一个标号位置
movl 8(%ebp), %eax                   #把立即数8放到EAX的寄存器
movl %eax,( %esp)                   #将EAX寄存器里的值放到ESP所指的位置
call g                                            #调用g函数,先将ESP后移,存储现在EIP寄存器内的值,然后EBP内的值压榨存储到下一标号位置

call g即再次进入g函数,f函数剩余部分继续等待执行

pushl %ebp                           #将EBP(栈基值)寄存器的值入栈
movl %esp, %ebp                 #让EBP和ESP指向同一个位置
movl 8(%ebp), %eax            #将EBP指针前两个标号位置的内容放入EAX运算单元内
addl $3,%eax                       #将EAX内的值+3
pool %ebp                            #将标号7放入EBP寄存器里,让EBP指针回归上一级函数的栈底
ret                                         #函数返回,将标号6内的值放入EIP寄存器内

g函数执行结束,跳转回f函数的剩余部分

 leave                                   #销毁f函数的这一部分工作站栈

ret                                        #函数返回,将标号3内的值放入EIP寄存器内

f函数执行完后,再重新跳回main函数执行剩余部分的main函数代码

addl $1,%eax                    #将EAX中内容加1,EAX寄存器是默认存储函数返回值的寄存器

leave                                    #销毁main函数工作栈

ret                                        #函数返回

二、基于ARM的配套实验一(ARM汇编语言)

        进入老师发布的Openeuler操作系统。将C语言编译成ARM汇编语言,最好使用本就是ARM架构的主机,因此这里推荐使用Openeuler操作系统。否则,对于使用X86架构的主机用户,将C语言代码编译成ARM汇编语言代码需要安装交叉编译环境,相对比较复杂。

1、编写main.c函数

2、通过命令编译成汇编代码

gcc –S –o main.s main.c

3、查看汇编文件main.s

 

4、进行汇编代码的多余代码删除

同样通过以下代码进行多余辅助文件的删除。

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

5、进行汇编代码的分析

 可以看到,X86汇编语言和ARM汇编语言还是非常不一样的,不过它们都和C语言一一对应。

g:
        sub     sp, sp, #16
        str     w0, [sp, 12]
        ldr     w0, [sp, 12]
        add     w0, w0, 3
        add     sp, sp, 16
        ret
f:
        stp     x29, x30, [sp, -32]!
        add     x29, sp, 0
        str     w0, [x29, 28]
        ldr     w0, [x29, 28]
        bl      g
        ldp     x29, x30, [sp], 32
        ret
main:
        stp     x29, x30, [sp, -16]!
        add     x29, sp, 0
        mov     w0, 0xba7f
        movk    w0, 0x134, lsl 16
        bl      f
        add     w0, w0, 1
        ldp     x29, x30, [sp], 16
        ret

首先是进入main函数

stp     x29, x30, [sp, -16]!     # x29、x30 分别压入栈中,即 sp – 16 的内存地址所在的 16 个字节的存储空间
add     x29, sp, 0                 #将栈顶地址赋给栈基址,构造了 main 函数的初始栈空间          
mov     w0, 0xba7f               #将 f 函数的参数20232831赋给寄存器 w0 进行传参。
movk    w0, 0x134, lsl 16    #将 f 函数的参数20232831赋给寄存器 w0 进行传参。

                                           #这里两个函数都说进行传参的,因为20232831太长,无法一次性完成传参。第一次传参是传入16进制数0xba7f,第二次传参是传入16进制数作为开头,即将0xba7f后移16位,再传入0x134,从而得到20232831=0x134ba7f。
bl      f                               #调用函数 f,先将下一指令地址保存到 x30 寄存器中,再进行跳转

下面进入f函数

f:
stp     x29, x30, [sp, -32]!     #将 x29 和 x30 压栈,只不过这里 sp 被回写成了 sp – 32,是为了多生成一些栈空间存放函数调用的参数,这会在后面的指令中体现。
add     x29, sp, 0                 #构造了 f 函数的初始栈空间。
str     w0, [x29, 28]              #将上 main 函数传递过来的参数从 w0 存入栈中
ldr     w0, [x29, 28]              #从栈中取回 w0
bl      g                                #跳转到g函数

下面进入g函数

 g:
sub     sp, sp, #16        #为 g 开辟了 16 个字节的栈空间,以存放 g 函数传来的参数
str     w0, [sp, 12]         #将参数从 w0 存入栈中
ldr     w0, [sp, 12]         #将参数从 w0 栈中取出
add     w0, w0, 3          #执行 +3 操作,准备作为返回值返回
add     sp, sp, 16         #将栈指针上移(销毁形参和临时变量)
ret                                #将 x30 寄存器的值赋给指令指针寄存器 PC,执行返回操作,回到f函数

回到f函数执行剩余部分

ldp     x29, x30, [sp], 32        #将 x29 和 x30 寄存器的内容退栈、销毁 f 的栈空间
ret                                         # x30 寄存器的值赋给指令指针寄存器 PC,执行返回操作,回到main函数

回到main函数执行剩余部分

add     w0, w0, 1                #将 f 函数的返回值 w0 加 1
ldp     x29, x30, [sp], 16     #将 x29 和 x30 寄存器的内容退栈、销毁 f 的栈空间
ret                                      #函数返回

 三、总结

        通过反编译成汇编语言的整个过程学习,能够知道更多关于计算机底层的运行逻辑。同时,X86和ARM两种不同的汇编语言的底层逻辑也稍有不同,通过对比学习了解了更多。总的来说,汇编还是相对复杂的部分,对了解计算机原理有非常大的帮助。

四、Chatgpt帮助

        

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值