林少华 失乐园:从汇编的角度分析C语言(一)char *p与char p[]的区别
来源:百度文库 编辑:偶看新闻 时间:2024/05/01 07:10:54
C语言代码:
view plaincopy to clipboardprint?- #include
- #include
- void main()
- {
- char array1[] = { "123456" };
- char *pointer1 = "123456";
- }
汇编代码:
view plaincopy to clipboardprint?- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x10,%esp
- 0x0804839a <+6>: movl $0x34333231,-0xb(%ebp)
- 0x080483a1 <+13>: movw $0x3635,-0x7(%ebp)
- 0x080483a7 <+19>: movb $0x0,-0x5(%ebp)
- 0x080483ab <+23>: movl $0x8048484,-0x4(%ebp)
- 0x080483b2 <+30>: leave
- 0x080483b3 <+31>: ret
- End of assembler dump.
- (gdb) x/7xb 0x8048484
- 0x8048484 <__dso_handle+4>: 0x31 0x32 0x33 0x34 0x35 0x36 0x00
- (gdb)
从<+6><+13><+19>三行可以看出,程序为array1分配了7bytes的内存空间,用来存储“123456”+‘\0’。
而<+23>行表示将地址0x8048484赋给了pointer1,我们可以查看内存0x8048484之后内容,7bytes正好为“123456”+‘\0’,这里pointer1只是一个指针,并没有为其分配内存单元。
那么下面的这段代码就不难理解了。
- #include
- #include
- void main()
- {
- char array1[] = { "123456" };
- char array2[] = { "123456" };
- char *pointer1 = "123456";
- char *pointer2 = "123456";
- }
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x20,%esp
- 0x0804839a <+6>: movl $0x34333231,-0xf(%ebp)
- 0x080483a1 <+13>: movw $0x3635,-0xb(%ebp)
- 0x080483a7 <+19>: movb $0x0,-0x9(%ebp)
- 0x080483ab <+23>: movl $0x34333231,-0x16(%ebp)
- 0x080483b2 <+30>: movw $0x3635,-0x12(%ebp)
- 0x080483b8 <+36>: movb $0x0,-0x10(%ebp)
- 0x080483bc <+40>: movl $0x8048494,-0x4(%ebp)
- 0x080483c3 <+47>: movl $0x8048494,-0x8(%ebp)
- 0x080483ca <+54>: leave
- 0x080483cb <+55>: ret
- End of assembler dump.
- (gdb) x/7xb 0x8048494
- 0x8048494 <__dso_handle+4>: 0x31 0x32 0x33 0x34 0x35 0x36 0x00
- (gdb)
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x20,%esp
- 0x0804839a <+6>: movl $0x34333231,-0xf(%ebp)
- 0x080483a1 <+13>: movw $0x3635,-0xb(%ebp)
- 0x080483a7 <+19>: movb $0x0,-0x9(%ebp)
- 0x080483ab <+23>: movl $0x34333231,-0x16(%ebp)
- 0x080483b2 <+30>: movw $0x3635,-0x12(%ebp)
- 0x080483b8 <+36>: movb $0x0,-0x10(%ebp)
- 0x080483bc <+40>: movl $0x8048494,-0x4(%ebp)
- 0x080483c3 <+47>: movl $0x804849b,-0x8(%ebp)
- 0x080483ca <+54>: leave
- 0x080483cb <+55>: ret
- End of assembler dump.
- (gdb) x/7xb 0x8048494
- 0x8048494 <__dso_handle+4>: 0x31 0x32 0x33 0x34 0x35 0x36 0x00
- (gdb) x/9xb 0x804849b
- 0x804849b <__dso_handle+11>: 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
- 0x80484a3 <__dso_handle+19>: 0x00
- (gdb)
从汇编的角度分析C语言(二)gcc代码的优化
- #include
- #include
未使用优化:
[root@ShiGuang test]# gcc -S main.c
view plaincopy to clipboardprint?
- .file "main.c"
- .text
- .globl main
- .type main, @function
- main:
- pushl %ebp
- movl %esp, %ebp
- subl $16, %esp
- movl $1, -4(%ebp)
- movl $2, -8(%ebp)
- movl -8(%ebp), %eax
- movl -4(%ebp), %edx
- leal (%edx,%eax), %eax
- movl %eax, -12(%ebp)
- movl -12(%ebp), %eax
- leave
- ret
- .size main, .-main
- .ident "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
- .section .note.GNU-stack,"",@progbits
优化处理:
[root@ShiGuang test]# gcc -S main.c -O2
view plaincopy to clipboardprint?
- .file "main.c"
- .text
- .p2align 4,,15
- globl main
- .type main, @function
- ain:
- pushl %ebp
- movl $3, %eax
- movl %esp, %ebp
- popl %ebp
- ret
- .size main, .-main
- .ident "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
- .section .note.GNU-stack,"",@progbits
优化结果还是很明显的!gcc对常数的合并与常数的传播,具有较好的优化处理。
我们从上面的两段汇编代码就能看出。
从汇编的角度分析C语言(三)指针的赋值
- #include
- #include
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x10,%esp
- 0x0804839a <+6>: movl $0x1,-0xc(%ebp)
- 0x080483a1 <+13>: lea -0xc(%ebp),%eax
- 0x080483a4 <+16>: mov %eax,-0x4(%ebp)
- 0x080483a7 <+19>: mov -0x4(%ebp),%eax
- 0x080483aa <+22>: mov %eax,-0x8(%ebp)
- 0x080483ad <+25>: mov -0x4(%ebp),%eax
- 0x080483b0 <+28>: movl $0x2,(%eax)
- 0x080483b6 <+34>: mov -0x8(%ebp),%eax
- 0x080483b9 <+37>: movl $0x3,(%eax)
- 0x080483bf <+43>: mov $0x0,%eax
- 0x080483c4 <+48>: leave
- 0x080483c5 <+49>: ret
- End of assembler dump.
- (gdb)
从汇编的角度分析C语言(四)函数的调用过程
- #include
- #include
- int add(int a, int b)
- {
- int c;
- c = a;
- c += b;
- return c;
- }
- int main()
- {
- int a, b, c;
- a = 0x12;
- b = 0x34;
- c = add(a, b);
- return 0;
- }
view plaincopy to clipboardprint?
- .file "main.c"
- .text
- .globl add
- .type add, @function
- add:
- pushl %ebp
- movl %esp, %ebp
- subl $16, %esp
- movl 8(%ebp), %eax
- movl %eax, -4(%ebp)
- movl 12(%ebp), %eax
- addl %eax, -4(%ebp)
- movl -4(%ebp), %eax
- leave
- ret
- .size add, .-add
- .globl main
- .type main, @function
- main:
- pushl %ebp
- movl %esp, %ebp
- subl $24, %esp
- movl $18, -4(%ebp)
- movl $52, -8(%ebp)
- movl -8(%ebp), %eax
- movl %eax, 4(%esp)
- movl -4(%ebp), %eax
- movl %eax, (%esp)
- call add
- movl %eax, -12(%ebp)
- movl $0, %eax
- leave
- ret
- .size main, .-main
- .ident "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
- .section .note.GNU-stack,"",@progbits
view plaincopy to clipboardprint?
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x080483ab <+0>: push %ebp
- 0x080483ac <+1>: mov %esp,%ebp
- 0x080483ae <+3>: sub $0x18,%esp
- 0x080483b1 <+6>: movl $0x12,-0x4(%ebp)
- 0x080483b8 <+13>: movl $0x34,-0x8(%ebp)
- 0x080483bf <+20>: mov -0x8(%ebp),%eax
- 0x080483c2 <+23>: mov %eax,0x4(%esp)
- 0x080483c6 <+27>: mov -0x4(%ebp),%eax
- 0x080483c9 <+30>: mov %eax,(%esp)
- 0x080483cc <+33>: call 0x8048394
- 0x080483d1 <+38>: mov %eax,-0xc(%ebp)
- 0x080483d4 <+41>: mov $0x0,%eax
- 0x080483d9 <+46>: leave
- 0x080483da <+47>: ret
- End of assembler dump.
- (gdb) list
- 6 int c;
- 7 c = a;
- 8 c += b;
- 9 return c;
- 10 }
- 11
- 12 int main()
- 13 {
- 14 int a, b, c;
- 15 a = 0x12;
- 16 b = 0x34;
- 17 c = add(a, b);
- 18 return 0;
- 19 }
- (gdb) break 17
- Breakpoint 1 at 0x80483bf: file main.c, line 17.
- (gdb) run
- Starting program: /home/my_project/test/main
- Breakpoint 1, main () at main.c:17
- 17 c = add(a, b);
- Missing separate debuginfos, use: debuginfo-install glibc-2.12.90-17.i686
- (gdb) info registers esp
- esp 0xbffff1e0 0xbffff1e0
- (gdb) info registers ebp
- ebp 0xbffff1f8 0xbffff1f8
- (gdb) x/6xw 0xbffff1e0
- 0xbffff1e0: 0x080483e0 0x080482e0 0x080483eb 0x00394ff4
- 0xbffff1f0: 0x00000034 0x00000012
- (gdb) step
- add (a=18, b=52) at main.c:7
- 7 c = a;
- (gdb) x/6xw 0xbffff1e0
- 0xbffff1e0: 0x00000012 0x00000034 0x080483eb 0x00394ff4
- 0xbffff1f0: 0x00000034 0x00000012
- (gdb) info registers esp
- esp 0xbffff1c8 0xbffff1c8
- (gdb) info registers ebp
- ebp 0xbffff1d8 0xbffff1d8
- (gdb) tep
- Undefined command: "tep". Try "help".
- (gdb) step
- 8 c += b;
- (gdb) step
- 9 return c;
- (gdb) x/16xw 0xbffff1c0
- 0xbffff1c0: 0x00235f95 0x08049624 0xbffff1f8 0x080483f9
- 0xbffff1d0: 0x08048215 0x00000046 0xbffff1f8 0x080483d1
- 0xbffff1e0: 0x00000012 0x00000034 0x080483eb 0x00394ff4
- 0xbffff1f0: 0x00000034 0x00000012 0xbffff278 0x0021ce16
- (gdb)step
- 10 }
- (gdb) step
- main () at main.c:18
- 18 return 0;
- (gdb) info registers esp
- esp 0xbffff1e0 0xbffff1e0
- (gdb) info registers ebp
- ebp 0xbffff1f8 0xbffff1f8
- (gdb)
红色是main函数分配的堆栈,绿色是add函数分配的堆栈
从汇编的角度分析C语言(五)函数指针与指针的指针
函数指针:
view plaincopy to clipboardprint?- #include
- #include
- void add()
- {
- printf("12\n");
- }
- int main()
- {
- int * func;
- func = (int *)add;
- return 0;
- }
- .file "main.c"
- .section .rodata
- .LC0:
- .string "12"
- .text
- .globl add
- .type add, @function
- add:
- pushl %ebp
- movl %esp, %ebp
- subl $24, %esp
- movl $.LC0, (%esp)
- call puts
- leave
- ret
- .size add, .-add
- .globl main
- .type main, @function
- main:
- pushl %ebp
- movl %esp, %ebp
- subl $16, %esp
- movl $add, -4(%ebp)
- movl $0, %eax
- leave
- ret
- .size main, .-main
- .ident "GCC: (GNU) 4.5.1 20100924 (Red Hat 4.5.1-4)"
- .section .note.GNU-stack,"",@progbits
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x080483c8 <+0>: push %ebp
- 0x080483c9 <+1>: mov %esp,%ebp
- 0x080483cb <+3>: sub $0x10,%esp
- 0x080483ce <+6>: movl $0x80483b4,-0x4(%ebp)
- 0x080483d5 <+13>: mov $0x0,%eax
- 0x080483da <+18>: leave
- 0x080483db <+19>: ret
- End of assembler dump.
- (gdb) p add
- $1 = {
variable, no debug info>} 0x80483b4 - (gdb)
指针的指针:
view plaincopy to clipboardprint?- #include
- #include
- void main()
- {
- int a = 0x12;
- int *p1 = &a;
- int **p2 = &p1;
- int ***p3 = &p3;
- }
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x10,%esp
- 0x0804839a <+6>: movl $0x12,-0x8(%ebp)
- 0x080483a1 <+13>: lea -0x8(%ebp),%eax
- 0x080483a4 <+16>: mov %eax,-0xc(%ebp)
- 0x080483a7 <+19>: lea -0xc(%ebp),%eax
- 0x080483aa <+22>: mov %eax,-0x4(%ebp)
- 0x080483ad <+25>: lea -0x10(%ebp),%eax
- 0x080483b0 <+28>: mov %eax,-0x10(%ebp)
- 0x080483b3 <+31>: leave
- 0x080483b4 <+32>: ret
- End of assembler dump.
- (gdb)
从汇编的角度分析C语言(六)switch和if else效率分析
switch语句分析:
view plaincopy to clipboardprint?
- #include
- #include
- void main()
- {
- int m = 0x12;
- switch(m)
- {
- case 0x12:
- m = m + 1;
- break;
- case 0x13:
- m = m + 2;
- break;
- default:
- break;
- }
- }
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x10,%esp
- 0x0804839a <+6>: movl $0x12,-0x4(%ebp)
- 0x080483a1 <+13>: mov -0x4(%ebp),%eax
- 0x080483a4 <+16>: cmp $0x12,%eax
- 0x080483a7 <+19>: je 0x80483b0 +28>
- 0x080483a9 <+21>: cmp $0x13,%eax
- 0x080483ac <+24>: je 0x80483b6 +34>
- 0x080483ae <+26>: jmp 0x80483bb +39>
- 0x080483b0 <+28>: addl $0x1,-0x4(%ebp)
- 0x080483b4 <+32>: jmp 0x80483bb +39>
- 0x080483b6 <+34>: addl $0x2,-0x4(%ebp)
- 0x080483ba <+38>: nop
- 0x080483bb <+39>: leave
- 0x080483bc <+40>: ret
- End of assembler dump.
- (gdb)
view plaincopy to clipboardprint?
- #include
- #include
- void main()
- {
- int m = 0x12;
- if( m == 0x12)
- m = m + 1;
- else if( m == 0x12)
- m = m + 1;
- else
- ;
- }
- (gdb) disassemble main
- Dump of assembler code for function main:
- 0x08048394 <+0>: push %ebp
- 0x08048395 <+1>: mov %esp,%ebp
- 0x08048397 <+3>: sub $0x10,%esp
- 0x0804839a <+6>: movl $0x12,-0x4(%ebp)
- 0x080483a1 <+13>: cmpl $0x12,-0x4(%ebp)
- 0x080483a5 <+17>: jne 0x80483ad +25>
- 0x080483a7 <+19>: addl $0x1,-0x4(%ebp)
- 0x080483ab <+23>: jmp 0x80483b7 +35>
- 0x080483ad <+25>: cmpl $0x12,-0x4(%ebp)
- 0x080483b1 <+29>: jne 0x80483b7 +35>
- 0x080483b3 <+31>: addl $0x1,-0x4(%ebp)
- 0x080483b7 <+35>: leave
- 0x080483b8 <+36>: ret
- End of assembler dump.
- (gdb)
void fun(char *a, char *b)?(C语言)
C语言关于CHAR类型的转换
c语言 char* 问题
c语言 char类型转换
汇编和c语言如何结合的?
c语言的题目struct STU {char num[10];
[C语言]为什么swap函数返回的是char类型?
请问如何分析一支想要介入的股票?大体从哪几个角度去分析?
静夜思 中英文比较赏析,从语言类型,特征,语言结构,音韵等的角度来分析,大家发发言吧
关于从政治角度分析的问题
从能量转化的角度分析一下,
从社会发展的角度出发分析自然资源
从自然环境角度分析欧洲人的饮食习惯
C语言中如何从一个文本文件中读入一个字符,放入char变量中?
请问C语言中 char far 是什么意思?
有没有什么书是从编译器角度介绍C语言的??
从硬件的角度详细分析一台电脑的配置情况及性能和功能
UNIX的编程通常有shell编程、高级语言编程(C/C++),从程序设计角度,请分别说明两种编程方式的不同。
怎么从经济学的角度分析"不在一棵树上吊死"
从个性与成功的角度分析一下杨澜(案例分析)
要求从market segmentation角度分析的企业案例分析
******C语言中调用汇编的方法…*****
求助!一个嵌套汇编的C语言程序!急~~~~~~
我有汇编的基础,但是我对C语言是个盲,所以现在想学C语言,请帮我推荐一本书