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

2022-2023-1 20222803 《Linux内核原理与分析》第二周作业,第1张

一、反汇编C程序

首先编写一个简单的C语言程序,过程如图所示:

使用命令gcc -S -o 20222803.s 20222803.c -m32可以将C语言代码文件20222803.c反汇编出汇编语言代码文件20222803.s20222803.s内容如下:

	.file	"20222803.c"
	.text
	.globl	g
	.type	g, @function
g:
.LFB0:
	.cfi_startproc
	endbr32
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	call	__x86.get_pc_thunk.ax
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	movl	8(%ebp), %eax
	addl	03, %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
	endbr32
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	call	__x86.get_pc_thunk.ax
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	pushl	8(%ebp)
	call	g
	addl	, %esp
	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
	endbr32
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	call	__x86.get_pc_thunk.ax
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	pushl	
	call	f
	addl	, %esp
	addl	, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE2:
	.size	main, .-main
	.section	.text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
	.globl	__x86.get_pc_thunk.ax
	.hidden	__x86.get_pc_thunk.ax
	.type	__x86.get_pc_thunk.ax, @function
__x86.get_pc_thunk.ax:
.LFB3:
	.cfi_startproc
	movl	(%esp), %eax
	ret
	.cfi_endproc
.LFE3:
	.ident	"GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 4
	.long	 1f - 0f
	.long	 4f - 1f
	.long	 5
0:
	.string	 "GNU"
1:
	.align 4
	.long	 0xc0000002
	.long	 3f - 2f
2:
	.long	 0x3
3:
	.align 4
4:

vim编辑器中,输入命令g/\.s*/d,删除所有以.打头的字符串,“美化”得到的汇编代码,如下所示:

g:
	endbr32
	pushl	%ebp
	movl	%esp, %ebp
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	movl	8(%ebp), %eax
	addl	03, %eax
	popl	%ebp
	ret
f:
	endbr32
	pushl	%ebp
	movl	%esp, %ebp
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	pushl	8(%ebp)
	call	g
	addl	, %esp
	leave
	ret
main:
	endbr32
	pushl	%ebp
	movl	%esp, %ebp
	addl	$_GLOBAL_OFFSET_TABLE_, %eax
	pushl	
	call	f
	addl	, %esp
	addl	, %eax
	leave
	ret
	movl	(%esp), %eax
	ret
二、汇编语言分析 main函数
代码片段含义
pushl %ebp将EBP寄存器的值也即栈底指针压栈
movl %esp, %ebp将ESP寄存器的值也即栈顶指针存入EBP寄存器
pushl 将28压栈
call f调用f函数
addl , %espESP寄存器的值加4,指向调用f函数前的栈顶
addl , %eaxEAX寄存器的值加3,即2831+3=2834
leave撤销函数堆栈
ret返回更上层的堆栈
f函数
代码片段含义
pushl %ebp将EBP寄存器的值也即栈底指针压栈
movl %esp, %ebp将ESP寄存器的值也即栈顶指针存入EBP寄存器
pushl 8(%ebp)将EBP寄存器的值加8,指向之前压入栈的数28,然后将28压栈
call g调用g函数
addl , %espESP寄存器的值加4,指向调用g函数前的栈顶
leave撤销调用函数的堆栈
ret回退到f函数调用的代码处
g函数
代码片段含义
pushl %ebp将EBP寄存器的值也即栈底指针压栈
movl %esp, %ebp将ESP寄存器的值也即栈顶指针存入EBP寄存器
movl 8(%ebp), %eax将EBP寄存器的值加8,指向之前压入栈的数28,将28存入EAX寄存器
addl 03, %eaxEAX寄存器的值加2803,即28+2803=2831
popl %ebp将栈顶数据存入EBP寄存器,也即调用g函数前的栈顶指针
ret回退到g函数调用的代码处

以上具体过程参考了完整汇编程序执行过程分析

遇到的问题

一、在虚拟机中反汇编失败,报错如图:


解决方法:是由于在64位系统上编译32位可执行程序缺少相应的32位库文件所致,在终端输入sudo apt-get install gcc-multilib之后解决。解决方法来自于“/usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: No such file or directory 报错解决”

二、对pushl 8(%ebp)的理解错误

解决方法:仔细查阅《庖丁解牛Linux 分析 》第25页内容得到解决。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/3002492.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存