<深入理解计算机系统> 通过程序的机器级表示来理解函数栈

C源码:

void swap(int *a,int *b)
{
   int c;
   c = *a;
   *a = *b;
   *b = c;
}

int main(void)
{
   int a ;
   int b ;
   int ret;
   a =16;
   b = 64;
   ret = 0;
   swap(&a,&b);
   ret = a - b;
   return ret;
}

编译:

gcc -g func_stack.c -o a.out
objdump -dS a.out > main.dump

可以得到反汇编的汇编程序main.dump, 有对应的C程序,如下所示:

a.out:     文件格式 elf32-i386

Disassembly of section .init:

08048294 <_init>:
 8048294:	53                   	push   %ebx
 8048295:	83 ec 08             	sub    $0x8,%esp
 8048298:	e8 83 00 00 00       	call   8048320 <__x86.get_pc_thunk.bx>
 804829d:	81 c3 63 1d 00 00    	add    $0x1d63,%ebx
 80482a3:	8b 83 fc ff ff ff    	mov    -0x4(%ebx),%eax
 80482a9:	85 c0                	test   %eax,%eax
 80482ab:	74 05                	je     80482b2 <_init+0x1e>
 80482ad:	e8 1e 00 00 00       	call   80482d0 <[email protected]>
 80482b2:	83 c4 08             	add    $0x8,%esp
 80482b5:	5b                   	pop    %ebx
 80482b6:	c3                   	ret    

Disassembly of section .plt:

080482c0 <[email protected]>:
 80482c0:	ff 35 04 a0 04 08    	pushl  0x804a004
 80482c6:	ff 25 08 a0 04 08    	jmp    *0x804a008
 80482cc:	00 00                	add    %al,(%eax)
	...

080482d0 <[email protected]>:
 80482d0:	ff 25 0c a0 04 08    	jmp    *0x804a00c
 80482d6:	68 00 00 00 00       	push   $0x0
 80482db:	e9 e0 ff ff ff       	jmp    80482c0 <_init+0x2c>

080482e0 <[email protected]>:
 80482e0:	ff 25 10 a0 04 08    	jmp    *0x804a010
 80482e6:	68 08 00 00 00       	push   $0x8
 80482eb:	e9 d0 ff ff ff       	jmp    80482c0 <_init+0x2c>

Disassembly of section .text:

080482f0 <_start>:
 80482f0:	31 ed                	xor    %ebp,%ebp
 80482f2:	5e                   	pop    %esi
 80482f3:	89 e1                	mov    %esp,%ecx
 80482f5:	83 e4 f0             	and    $0xfffffff0,%esp
 80482f8:	50                   	push   %eax
 80482f9:	54                   	push   %esp
 80482fa:	52                   	push   %edx
 80482fb:	68 c0 84 04 08       	push   $0x80484c0
 8048300:	68 50 84 04 08       	push   $0x8048450
 8048305:	51                   	push   %ecx
 8048306:	56                   	push   %esi
 8048307:	68 0f 84 04 08       	push   $0x804840f
 804830c:	e8 cf ff ff ff       	call   80482e0 <[email protected]>
 8048311:	f4                   	hlt
 8048312:	66 90                	xchg   %ax,%ax
 8048314:	66 90                	xchg   %ax,%ax
 8048316:	66 90                	xchg   %ax,%ax
 8048318:	66 90                	xchg   %ax,%ax
 804831a:	66 90                	xchg   %ax,%ax
 804831c:	66 90                	xchg   %ax,%ax
 804831e:	66 90                	xchg   %ax,%ax

08048320 <__x86.get_pc_thunk.bx>:
 8048320:	8b 1c 24             	mov    (%esp),%ebx
 8048323:	c3                   	ret
 8048324:	66 90                	xchg   %ax,%ax
 8048326:	66 90                	xchg   %ax,%ax
 8048328:	66 90                	xchg   %ax,%ax
 804832a:	66 90                	xchg   %ax,%ax
 804832c:	66 90                	xchg   %ax,%ax
 804832e:	66 90                	xchg   %ax,%ax

08048330 <deregister_tm_clones>:
 8048330:	b8 1f a0 04 08       	mov    $0x804a01f,%eax
 8048335:	2d 1c a0 04 08       	sub    $0x804a01c,%eax
 804833a:	83 f8 06             	cmp    $0x6,%eax
 804833d:	77 01                	ja     8048340 <deregister_tm_clones+0x10>
 804833f:	c3                   	ret
 8048340:	b8 00 00 00 00       	mov    $0x0,%eax
 8048345:	85 c0                	test   %eax,%eax
 8048347:	74 f6                	je     804833f <deregister_tm_clones+0xf>
 8048349:	55                   	push   %ebp
 804834a:	89 e5                	mov    %esp,%ebp
 804834c:	83 ec 18             	sub    $0x18,%esp
 804834f:	c7 04 24 1c a0 04 08 	movl   $0x804a01c,(%esp)
 8048356:	ff d0                	call   *%eax
 8048358:	c9                   	leave
 8048359:	c3                   	ret
 804835a:	8d b6 00 00 00 00    	lea    0x0(%esi),%esi

08048360 <register_tm_clones>:
 8048360:	b8 1c a0 04 08       	mov    $0x804a01c,%eax
 8048365:	2d 1c a0 04 08       	sub    $0x804a01c,%eax
 804836a:	c1 f8 02             	sar    $0x2,%eax
 804836d:	89 c2                	mov    %eax,%edx
 804836f:	c1 ea 1f             	shr    $0x1f,%edx
 8048372:	01 d0                	add    %edx,%eax
 8048374:	d1 f8                	sar    %eax
 8048376:	75 01                	jne    8048379 <register_tm_clones+0x19>
 8048378:	c3                   	ret
 8048379:	ba 00 00 00 00       	mov    $0x0,%edx
 804837e:	85 d2                	test   %edx,%edx
 8048380:	74 f6                	je     8048378 <register_tm_clones+0x18>
 8048382:	55                   	push   %ebp
 8048383:	89 e5                	mov    %esp,%ebp
 8048385:	83 ec 18             	sub    $0x18,%esp
 8048388:	89 44 24 04          	mov    %eax,0x4(%esp)
 804838c:	c7 04 24 1c a0 04 08 	movl   $0x804a01c,(%esp)
 8048393:	ff d2                	call   *%edx
 8048395:	c9                   	leave
 8048396:	c3                   	ret
 8048397:	89 f6                	mov    %esi,%esi
 8048399:	8d bc 27 00 00 00 00 	lea    0x0(%edi,%eiz,1),%edi

080483a0 <__do_global_dtors_aux>:
 80483a0:	80 3d 1c a0 04 08 00 	cmpb   $0x0,0x804a01c
 80483a7:	75 13                	jne    80483bc <__do_global_dtors_aux+0x1c>
 80483a9:	55                   	push   %ebp
 80483aa:	89 e5                	mov    %esp,%ebp
 80483ac:	83 ec 08             	sub    $0x8,%esp
 80483af:	e8 7c ff ff ff       	call   8048330 <deregister_tm_clones>
 80483b4:	c6 05 1c a0 04 08 01 	movb   $0x1,0x804a01c
 80483bb:	c9                   	leave
 80483bc:	f3 c3                	repz ret
 80483be:	66 90                	xchg   %ax,%ax

080483c0 <frame_dummy>:
 80483c0:	a1 10 9f 04 08       	mov    0x8049f10,%eax
 80483c5:	85 c0                	test   %eax,%eax
 80483c7:	74 1f                	je     80483e8 <frame_dummy+0x28>
 80483c9:	b8 00 00 00 00       	mov    $0x0,%eax
 80483ce:	85 c0                	test   %eax,%eax
 80483d0:	74 16                	je     80483e8 <frame_dummy+0x28>
 80483d2:	55                   	push   %ebp
 80483d3:	89 e5                	mov    %esp,%ebp
 80483d5:	83 ec 18             	sub    $0x18,%esp
 80483d8:	c7 04 24 10 9f 04 08 	movl   $0x8049f10,(%esp)
 80483df:	ff d0                	call   *%eax
 80483e1:	c9                   	leave
 80483e2:	e9 79 ff ff ff       	jmp    8048360 <register_tm_clones>
 80483e7:	90                   	nop
 80483e8:	e9 73 ff ff ff       	jmp    8048360 <register_tm_clones>

080483ed <swap>:
/*main.c代码:*/

void swap(int *a,int *b)
{
 80483ed:	55                   	push   %ebp
 80483ee:	89 e5                	mov    %esp,%ebp
 80483f0:	83 ec 10             	sub    $0x10,%esp
   int c;
   c = *a;
 80483f3:	8b 45 08             	mov    0x8(%ebp),%eax
 80483f6:	8b 00                	mov    (%eax),%eax
 80483f8:	89 45 fc             	mov    %eax,-0x4(%ebp)
   *a = *b;
 80483fb:	8b 45 0c             	mov    0xc(%ebp),%eax
 80483fe:	8b 10                	mov    (%eax),%edx
 8048400:	8b 45 08             	mov    0x8(%ebp),%eax
 8048403:	89 10                	mov    %edx,(%eax)
   *b = c;
 8048405:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048408:	8b 55 fc             	mov    -0x4(%ebp),%edx
 804840b:	89 10                	mov    %edx,(%eax)
}
 804840d:	c9                   	leave
 804840e:	c3                   	ret    

0804840f <main>:

int main(void)
{
 804840f:	55                   	push   %ebp
 8048410:	89 e5                	mov    %esp,%ebp
 8048412:	83 ec 18             	sub    $0x18,%esp
   int a ;
   int b ;
   int ret;
   a =16;
 8048415:	c7 45 f4 10 00 00 00 	movl   $0x10,-0xc(%ebp)
   b = 64;
 804841c:	c7 45 f8 40 00 00 00 	movl   $0x40,-0x8(%ebp)
   ret = 0;
 8048423:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%ebp)
   swap(&a,&b);
 804842a:	8d 45 f8             	lea    -0x8(%ebp),%eax
 804842d:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048431:	8d 45 f4             	lea    -0xc(%ebp),%eax
 8048434:	89 04 24             	mov    %eax,(%esp)
 8048437:	e8 b1 ff ff ff       	call   80483ed <swap>
   ret = a - b;
 804843c:	8b 55 f4             	mov    -0xc(%ebp),%edx
 804843f:	8b 45 f8             	mov    -0x8(%ebp),%eax
 8048442:	29 c2                	sub    %eax,%edx
 8048444:	89 d0                	mov    %edx,%eax
 8048446:	89 45 fc             	mov    %eax,-0x4(%ebp)
   return ret;
 8048449:	8b 45 fc             	mov    -0x4(%ebp),%eax
}
 804844c:	c9                   	leave
 804844d:	c3                   	ret
 804844e:	66 90                	xchg   %ax,%ax

08048450 <__libc_csu_init>:
 8048450:	55                   	push   %ebp
 8048451:	57                   	push   %edi
 8048452:	31 ff                	xor    %edi,%edi
 8048454:	56                   	push   %esi
 8048455:	53                   	push   %ebx
 8048456:	e8 c5 fe ff ff       	call   8048320 <__x86.get_pc_thunk.bx>
 804845b:	81 c3 a5 1b 00 00    	add    $0x1ba5,%ebx
 8048461:	83 ec 1c             	sub    $0x1c,%esp
 8048464:	8b 6c 24 30          	mov    0x30(%esp),%ebp
 8048468:	8d b3 0c ff ff ff    	lea    -0xf4(%ebx),%esi
 804846e:	e8 21 fe ff ff       	call   8048294 <_init>
 8048473:	8d 83 08 ff ff ff    	lea    -0xf8(%ebx),%eax
 8048479:	29 c6                	sub    %eax,%esi
 804847b:	c1 fe 02             	sar    $0x2,%esi
 804847e:	85 f6                	test   %esi,%esi
 8048480:	74 27                	je     80484a9 <__libc_csu_init+0x59>
 8048482:	8d b6 00 00 00 00    	lea    0x0(%esi),%esi
 8048488:	8b 44 24 38          	mov    0x38(%esp),%eax
 804848c:	89 2c 24             	mov    %ebp,(%esp)
 804848f:	89 44 24 08          	mov    %eax,0x8(%esp)
 8048493:	8b 44 24 34          	mov    0x34(%esp),%eax
 8048497:	89 44 24 04          	mov    %eax,0x4(%esp)
 804849b:	ff 94 bb 08 ff ff ff 	call   *-0xf8(%ebx,%edi,4)
 80484a2:	83 c7 01             	add    $0x1,%edi
 80484a5:	39 f7                	cmp    %esi,%edi
 80484a7:	75 df                	jne    8048488 <__libc_csu_init+0x38>
 80484a9:	83 c4 1c             	add    $0x1c,%esp
 80484ac:	5b                   	pop    %ebx
 80484ad:	5e                   	pop    %esi
 80484ae:	5f                   	pop    %edi
 80484af:	5d                   	pop    %ebp
 80484b0:	c3                   	ret
 80484b1:	eb 0d                	jmp    80484c0 <__libc_csu_fini>
 80484b3:	90                   	nop
 80484b4:	90                   	nop
 80484b5:	90                   	nop
 80484b6:	90                   	nop
 80484b7:	90                   	nop
 80484b8:	90                   	nop
 80484b9:	90                   	nop
 80484ba:	90                   	nop
 80484bb:	90                   	nop
 80484bc:	90                   	nop
 80484bd:	90                   	nop
 80484be:	90                   	nop
 80484bf:	90                   	nop

080484c0 <__libc_csu_fini>:
 80484c0:	f3 c3                	repz ret 

Disassembly of section .fini:

080484c4 <_fini>:
 80484c4:	53                   	push   %ebx
 80484c5:	83 ec 08             	sub    $0x8,%esp
 80484c8:	e8 53 fe ff ff       	call   8048320 <__x86.get_pc_thunk.bx>
 80484cd:	81 c3 33 1b 00 00    	add    $0x1b33,%ebx
 80484d3:	83 c4 08             	add    $0x8,%esp
 80484d6:	5b                   	pop    %ebx
 80484d7:	c3                   	ret    

下面将根据main/swap/start来讲述对应的汇编代码,来理解系统的函数栈是怎么调用的.

-------待续---------------------

参考:

点击打开链接

点击打开链接

时间: 2024-11-07 07:40:14

<深入理解计算机系统> 通过程序的机器级表示来理解函数栈的相关文章

深入理解计算机系统之程序的机器级表示部分学习笔记

不论我们是在用C语言还是用JAVA或是其他的语言编程时,我们会被屏蔽了程序的机器级的实现.机器语言不需要被编译,可以直接被CPU执行,其执行速度十分  快.但是机器语言的读写性与移植性较高级语言低.高级语言被编译后便成为了汇编语言,汇编语言十分接近机器语言.之后汇编代码会转化为机器语言.虽然现代  的编译器能帮助我们将高级语言转化为汇编语言,解决了不少问题,但是对于一个严谨的程序员来说,需要做到能够阅读和理解汇编语言.我们主要围绕Intel来讲  解. 一  Intel处理器的历史演变 Inte

深入理解计算机系统(第二版)----之三:程序的机器级表示

计算机执行机器代码,用字节编码低级的操作,包括处理数据.管理存储器.读写存储设备上的数据,利用网络通信,编译器基于变成语言的原则, 目标机器的指令集合操作系统遵循的原则,经过一系列阶段产生机器代码,gcc c语言编辑器以汇编代码的形式输出,汇编代码是机器代码的文本表示,给出程序的每一条指令.然后gcc调用汇编器和链接器,根据汇编代码生成可执行的机器代码. 本章,近距离观察机器代码和汇编代码. 机器级的实现,被高级语言屏蔽了,用高级语言编写的程序可以在很多不同的机器上编译和执行,而汇编代码则是与特

第三章程序的机器级表示 学习报告

第三章 程序的机器级表示 3.1 历史观点 Intel处理器系列俗称x86,开始时是第一代单芯片.16位微处理器之一. 每个后继处理器的设计都是后向兼容的——较早版本上编译的代码可以在较新的处理器上运行. X86 寻址方式经历三代: 1  DOS时代的平坦模式,不区分用户空间和内核空间,很不安全 2  8086的分段模式 3  IA32的带保护模式的平坦模式 3.2 程序编码 gcc -01 -o p p1.c -01 表示使用第一级优化.优化的级别与编译时间和最终产生代码的形式都有关系,一般认

第三章 程序的机器级表示

程序的机器级表示 3.1历史观点 8086—〉80286—〉i386—〉i486—〉Pentium—〉PentiumPro—〉Pentium—〉Pentium—〉Pentium4—〉Pentium4e—〉Core 2 Duo —〉Core i7 3.2程序编码 1.gcc -01 –o p p1.c p2.c      使用第一级优化 2.程序计数器(%eip)指示将要执行的下一条指令在存储器中的地址. 3.寄存器文件 4.-S:C语言编译器产生的汇编代码 例:gcc -01 –S code.c

CSAPP:第三章程序的机器级表示2

CSAPP:程序的机器级表示2 关键点:算术.逻辑操作 算术逻辑操作1.加载有效地址2.一元二元操作3.移位操作 算术逻辑操作 ??如图列出了x86-64的一些整数和逻辑操作,大多数操作分成了指令类(只有leaq没有其他的变种,addb.addw.addl.addq分别是字节加法.字加法.双字加法和四字加法),这些操作通常分为四组:加载有效地址.一元操作.二元操作和移位操作. 1.加载有效地址 leaq S,D;D = &S??加载有效地址指令leag实际上是movq指令的变形,它的指令形式上是

程序的机器级表示——基础

计算机执行的是机器代码,机器代码是二进制文件,既程序.机器代码用字节(1Byte=8bit)序列编码低级的操作,例如数据处理,管理存储器,从存储设备取数据等.使用高级语言(c,c++等)编写的程序(文本形式)最终需要被编译成机器代码才可以被计算机执行.当使用GCC c编译器来编译c语言代码时,会首先将其编译成汇编语言形式的内容,然后c编译器调用汇编器和连接器来最终形成计算机可执行的机器代码.汇编语言代码是机器码的文本形式,是机器码(字节序列)的文本助记形式.现在的要求是可以理解经过编译器优化过的

六星经典CSAPP-笔记(3)程序的机器级表示

1.前言 IA32机器码以及汇编代码都与原始的C代码有很大不同,因为一些状态对于C程序员来说是隐藏的.例如包含下一条要执行代码的内存位置的程序指针(program counter or PC)以及8个寄存器.还要注意的一点是:汇编代码的ATT格式和Intel格式.ATT格式是GCC和objdump等工具的默认格式,在CSAPP中一律使用这种格式.而Intel格式则通常会在Intel的IA32架构文档以及微软的Windows技术文档中碰到.两者的主要区别有: Intel格式忽略指令中暗示操作数长度

C语言程序的机器级表示

过程调用的机器级表示 特别说明该表示是基于IA-32指令系统,x86 64指令系统不同于IA-32 机器级表示 可执行文件的存储器映像 调用过程 IA-32的寄存器使用约定 – 调用者保存寄存器:EAX.EDX.ECX 当过程P调用过程Q时,Q可以直接使用这三个寄存器,不用 将它们的值保存到栈中.如果P在从Q返回后还要用这三个寄 存器的话,P应在转到Q之前先保存,并在从Q返回后先恢复 它们的值再使用. – 被调用者保存寄存器:EBX.ESI.EDI Q必须先将它们的值保存到栈中再使用它们,并在返

程序的机器级表示

P104,p105:     X86,经历了一个长期的的不断发展的过程.开始时他是第一代单芯片和16位微处理器之一,由于当时集成电路技术水平十分有限,其中做了很多妥协.此后,他不断地成长,利用进步的技术满足更高性能和支持更高级的操作系统的需求. 8086(1978) 80286(1982) i386(1985) i486(1989) Pentium(1993) PentiumPro(1995) Pentium II(1997) Pentium III(1999) Pentium 4(2000)