免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7095 | 回复: 12
打印 上一主题 下一主题

简易学习汇编 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-18 09:27 |只看该作者 |倒序浏览
这几种常用指令的作用要知道其含义
  1. push xxx == rsp <- rsp-8; [rsp] <- xxx
  2. pop xxx == xxx <- [rsp]; rsp <- rsp+8
  3. call xxx == push rip; rip <- xxx
  4. ret == pop rip
  5. leave == mov rsp, rbp; pop rbp
复制代码
AT&T汇编一般有这样的格式。
  1. .section .data
  2.         初始化的数据
  3. .section .bss
  4.         未初始化的数据
  5. .section .rodata
  6.         只读数据
  7. .section .text
  8. .globl _start
  9. _start:
  10.         指令序列
复制代码
通常可以使用
  1. as -o xxx.o xxx.s
  2. ld -o xxx xxx.o
复制代码
来汇编和链接
  1. .section .text
  2. .globl _start
  3. _start:
复制代码
改成
  1. .section .text
  2. .globl main
  3. main:
复制代码
即可使用gcc(其实gcc只是一个driver)来编译
  1. gcc -o xxx xxx.s
复制代码
如果你使用as和ld的话,可以使用别的标号来代替_start,只要在ld的-e参数指明入口点标号就行(当然你还可以修改.section信息,通过ld的参数或者脚本来控制)
,如果需要生成gdb可解析的符号表,使得程序可以用gdb调试,就使用
  1. as -gstabs -o xxx.o xxx.s
复制代码
,如果使用了库函数则要用
  1. ld -dynamic-linker /lib/ld-linux-x86-64.so.2 xxx -lc xxx.o
复制代码
来链接,或者直接使用
  1. gcc -o xxx xxx.s
复制代码
,前提是你的汇编代码入口是main
一般人几乎不会直接使用汇编,所以编译器就成了汇编器的最大用户,这里我们来用反汇编的方法学习汇编的框架,至于指令的细节是一定要去查看Inte和AMD手册的。如果你不满足于算法对效率的提升还想在指令级手工优化代码,或者想让编译器生成更加优化的代码,Intel 64 and IA-32 Architectures Optimization Reference Manual是非常值得推荐的。
  1. #include <stdio.h>

  2. int main()
  3. {
  4.         int a = 1;
  5.         int b = 2;

  6.         if(a > b)
  7.                 printf("a:%d is bigger\n", a);
  8.         else
  9.                 printf("b:%d is bigger\n", b);

  10.         return 0;
  11. }
复制代码
然后用
  1. gcc -S a.c
复制代码
编译代码,就会在当前目录下生成一个对应的汇编文件a.s
  1.         .file        "a.c"
  2.         .section        .rodata------两个字符串常量是只读的
  3. .LC0:
  4.         .string        "a:%d is bigger\n"
  5. .LC1:
  6.         .string        "b:%d is bigger\n"
  7.         .text
  8. .globl main
  9.         .type        main, @function------主函数
  10. main:
  11. .LFB2:----------------------
  12.         pushq        %rbp---------------pushq,64位,所以是q。保存rbp,以便使用rbp作为栈指针
  13. .LCFI0:
  14.         movq        %rsp, %rbp-----------保存栈frame,现在有些编译器开发者致力于优化函数调用,优化这个frame就是其中一项
  15. .LCFI1:
  16.         subq        $16, %rsp------------调整rsp,为变量留下空间
  17. .LCFI2:---------------------
  18.         movl        $1, -4(%rbp)------把常量1(a)入栈,占4个字节。EMT64下int是4字节的
  19.         movl        $2, -8(%rbp)------把常量2(b)入栈,占4个字节
  20.         movl        -4(%rbp), %eax-----从栈中把1放到eax中去
  21.         cmpl        -8(%rbp), %eax-----比较栈中的2和eax中的1
  22.         jle        .L2-----------如果cmp操作的第2个操作数小于或等于cmp操作的第1个操作数就jmp到.L2,注意AT&T语法和Intel语法的不同,操作数的顺序是相反的
  23.         movl        -4(%rbp), %esi
  24.         movl        $.LC0, %edi
  25.         movl        $0, %eax
  26.         call        printf
  27.         jmp        .L4
  28. .L2:------------else部分---------gcc4的函数调用规范-----------
  29.         movl        -8(%rbp), %esi------从栈中取b的值放入esi
  30.         movl        $.LC1, %edi-------把字符串"b:%d is bigger\n"的地址放入edi
  31.         movl        $0, %eax---------把0放入eax
  32.         call        printf----------调用printf函数
  33. .L4:
  34.         movl        $0, %eax---------return 0;这一句的返回值0放在eax中
  35.         leave---------------离开这个frame
  36.         ret----------------返回
  37. .LFE2:
  38.         .size        main, .-main
  39.         .section        .eh_frame,"a",@progbits
  40. .Lframe1:
  41.         .long        .LECIE1-.LSCIE1
  42. .LSCIE1:
  43.         .long        0x0
  44.         .byte        0x1
  45.         .string        "zR"
  46.         .uleb128 0x1
  47.         .sleb128 -8
  48.         .byte        0x10
  49.         .uleb128 0x1
  50.         .byte        0x3
  51.         .byte        0xc
  52.         .uleb128 0x7
  53.         .uleb128 0x8
  54.         .byte        0x90
  55.         .uleb128 0x1
  56.         .align 8
  57. .LECIE1:
  58. .LSFDE1:
  59.         .long        .LEFDE1-.LASFDE1
  60. .LASFDE1:
  61.         .long        .LASFDE1-.Lframe1
  62.         .long        .LFB2
  63.         .long        .LFE2-.LFB2
  64.         .uleb128 0x0
  65.         .byte        0x4
  66.         .long        .LCFI0-.LFB2
  67.         .byte        0xe
  68.         .uleb128 0x10
  69.         .byte        0x86
  70.         .uleb128 0x2
  71.         .byte        0x4
  72.         .long        .LCFI1-.LCFI0
  73.         .byte        0xd
  74.         .uleb128 0x6
  75.         .align 8
  76. .LEFDE1:
  77.         .ident        "GCC: (GNU) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)"
  78.         .section        .note.GNU-stack,"",@progbits
复制代码
如果if条件比较复杂比如
  1. if(condition1 || condition2)
复制代码
  1. if(condition1 && condition2)
复制代码
就分别使用
  1. cmpx x1, x2
  2. jxx xx
  3. cmpx x3, x4
  4. jxx xxx
复制代码
  1. cmpx x1, x2
  2. jxx L
  3. .L:
  4. cmpx x3, x4
  5. jxx xxx
复制代码
分别与之对应
  1. #include <stdio.h>

  2. int main()
  3. {
  4.         int i;
  5.         int j = 0;

  6.                 for(i = 0; i <= 3;  i++){
  7.                 j += i;
  8.                 printf("j is %d\n", j);
  9.         }

  10.         return 0;
  11. }
复制代码
  1.         .file        "a.c"
  2.         .section        .rodata
  3. .LC0:
  4.         .string        "j is %d\n"
  5.         .text
  6. .globl main
  7.         .type        main, @function
  8. main:
  9. .LFB2:
  10.         pushq        %rbp
  11. .LCFI0:
  12.         movq        %rsp, %rbp
  13. .LCFI1:
  14.         subq        $16, %rsp
  15. .LCFI2:
  16.         movl        $0, -8(%rbp)------- i
  17.         movl        $0, -4(%rbp)------- j
  18.         jmp        .L2
  19. .L3:
  20.         movl        -4(%rbp), %eax------ i
  21.         addl        %eax, -8(%rbp)------ j += i
  22.         movl        -8(%rbp), %esi
  23.         movl        $.LC0, %edi
  24.         movl        $0, %eax
  25.         call        printf
  26.         addl        $1, -4(%rbp)------------- i++
  27. .L2:
  28.         cmpl        $3, -4(%rbp)-------------
  29.         jle        .L3----------------- i <=3
  30.         movl        $0, %eax------返回值
  31.         leave
  32.         ret
  33. .LFE2:
  34.         .size        main, .-main
  35.         .section        .eh_frame,"a",@progbits
复制代码
  1. #include <stdio.h>

  2. int main()
  3. {
  4.         int i = 3;
  5.         int j = 0;

  6.         while(i >= 0){
  7.                 j += i;
  8.                 i--;
  9.                 printf("j is %d\n", j);
  10.         }

  11.         return 0;
  12. }
复制代码
  1.         .file        "a.c"
  2.         .section        .rodata
  3. .LC0:
  4.         .string        "j is %d\n"
  5.         .text
  6. .globl main
  7.         .type        main, @function
  8. main:
  9. .LFB2:
  10.         pushq        %rbp
  11. .LCFI0:
  12.         movq        %rsp, %rbp
  13. .LCFI1:
  14.         subq        $16, %rsp
  15. .LCFI2:
  16.         movl        $3, -4(%rbp)
  17.         movl        $0, -8(%rbp)
  18.         jmp        .L2
  19. .L3:
  20.         movl        -4(%rbp), %eax
  21.         addl        %eax, -8(%rbp)
  22.         subl        $1, -4(%rbp)--------------- i--
  23.         movl        -8(%rbp), %esi
  24.         movl        $.LC0, %edi
  25.         movl        $0, %eax
  26.         call        printf
  27. .L2:
  28.         cmpl        $0, -4(%rbp)---------------
  29.         jns        .L3-------------------- i >= 0
  30.         movl        $0, %eax
  31.         leave
  32.         ret
  33. .LFE2:
  34.         .size        main, .-main
  35.         .section        .eh_frame,"a",@progbits
复制代码
  1. #include <stdio.h>

  2. int main()
  3. {
  4.         int i = 3;
  5.         int j = 0;

  6.         do{
  7.                 j += i;
  8.                 i--;
  9.                 printf("j is %d\n", j);
  10.         }while(i >= 0);

  11.         return 0;
  12. }
复制代码
  1.         .file        "a.c"
  2.         .section        .rodata
  3. .LC0:
  4.         .string        "j is %d\n"
  5.         .text
  6. .globl main
  7.         .type        main, @function
  8. main:
  9. .LFB2:
  10.         pushq        %rbp
  11. .LCFI0:
  12.         movq        %rsp, %rbp
  13. .LCFI1:
  14.         subq        $16, %rsp
  15. .LCFI2:
  16.         movl        $3, -4(%rbp)
  17.         movl        $0, -8(%rbp)
  18. .L2:
  19.         movl        -4(%rbp), %eax
  20.         addl        %eax, -8(%rbp)
  21.         subl        $1, -4(%rbp)
  22.         movl        -8(%rbp), %esi
  23.         movl        $.LC0, %edi
  24.         movl        $0, %eax
  25.         call        printf
  26.         cmpl        $0, -4(%rbp)-----------
  27.         jns        .L2---------------- while(i >= 0);
  28.         movl        $0, %eax
  29.         leave
  30.         ret
  31. .LFE2:
  32.         .size        main, .-main
  33.         .section        .eh_frame,"a",@progbits
复制代码
  1. #include <stdio.h>

  2. int a = 6;
  3. int b = 5;

  4. int add(int x, int y)
  5. {
  6.         int z;
  7.         z = x + y;
  8.         return z;
  9. }

  10. int main()
  11. {
  12.         int m;

  13.         add(a, b);
  14.         //printf("%d\n", add(a, b));

  15.         return 0;
  16. }
复制代码
生成的汇编是
  1.         .file        "a.c"
  2. .globl a-----------全局变量a
  3.         .data-----------数据段
  4.         .align 4----------4字节对齐
  5.         .type        a, @object-----a是一个对象
  6.         .size        a, 4--------大小4字节
  7. a:
  8.         .long        6-----------a的值是6
  9. .globl b
  10.         .align 4
  11.         .type        b, @object
  12.         .size        b, 4
  13. b:
  14.         .long        5
  15.         .text
  16. .globl add
  17.         .type        add, @function-------------全局函数add
  18. add:
  19. .LFB2:
  20.         pushq        %rbp
  21. .LCFI0:
  22.         movq        %rsp, %rbp
  23. .LCFI1:
  24.         movl        %edi, -20(%rbp)
  25.         movl        %esi, -24(%rbp)
  26.         movl        -24(%rbp), %eax
  27.         addl        -20(%rbp), %eax
  28.         movl        %eax, -4(%rbp)
  29.         movl        -4(%rbp), %eax------------eax保存返回值
  30.         leave
  31.         ret
  32. .LFE2:
  33.         .size        add, .-add
  34. .globl main
  35.         .type        main, @function
  36. main:
  37. .LFB3:
  38.         pushq        %rbp
  39. .LCFI2:
  40.         movq        %rsp, %rbp
  41. .LCFI3:
  42.         subq        $16, %rsp
  43. .LCFI4:
  44.         movl        b(%rip), %esi
  45.         movl        a(%rip), %edi
  46.         call        add
  47.         movl        $0, %eax
  48.         leave
  49.         ret
  50. .LFE3:
  51.         .size        main, .-main
  52.         .section        .eh_frame,"a",@progbits
复制代码
还可以继续实验加入各种变量和函数还会见到.coom等标识,这样学习汇编不错。

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
2 [报告]
发表于 2008-06-18 09:40 |只看该作者
呵呵,不错。64位的

论坛徽章:
0
3 [报告]
发表于 2008-06-18 09:44 |只看该作者

回复 #2 cjaizss 的帖子

我的机器是intel core2的

论坛徽章:
0
4 [报告]
发表于 2008-06-18 17:19 |只看该作者
good job...

论坛徽章:
3
CU大牛徽章
日期:2013-03-13 15:32:35CU大牛徽章
日期:2013-03-13 15:38:15CU大牛徽章
日期:2013-03-13 15:38:52
5 [报告]
发表于 2008-07-04 00:50 |只看该作者
收藏先,汇编也快忘了……

论坛徽章:
0
6 [报告]
发表于 2008-07-04 13:20 |只看该作者
好贴

论坛徽章:
0
7 [报告]
发表于 2008-07-04 15:43 |只看该作者
very clear

论坛徽章:
0
8 [报告]
发表于 2009-01-15 15:29 |只看该作者
下面这些代码是什么意思哟
        .long        .LASFDE1-.Lframe1
        .long        .LFB2
        .long        .LFE2-.LFB2
        .uleb128 0x0
        .byte        0x4
        .long        .LCFI0-.LFB2
        .byte        0xe
        .uleb128 0x10
        .byte        0x86
        .uleb128 0x2
        .byte        0x4
        .long        .LCFI1-.LCFI0
        .byte        0xd
        .uleb128 0x6
        .align 8

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
9 [报告]
发表于 2009-01-15 15:47 |只看该作者
原帖由 skybyte 于 2009-1-15 15:29 发表
下面这些代码是什么意思哟
        .long        .LASFDE1-.Lframe1
        .long        .LFB2
        .long        .LFE2-.LFB2
        .uleb128 0x0
        .byte        0x4
        .long      ...

定了一堆内存
在这里可能是对一个C语言结构初始化的编译

论坛徽章:
0
10 [报告]
发表于 2009-01-15 18:47 |只看该作者
没有人把这样的好帖做成精华帖啊。有点可惜啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP