简易学习汇编

发布于 2022-09-19 12:31:24 字数 24014 浏览 20 评论 0

这几种常用指令的作用要知道其含义

  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等标识,这样学习汇编不错。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

長街聽風 2022-09-26 12:31:24

呵呵,不错。64位的

苍景流年 2022-09-26 12:31:24

我的机器是intel core2的

冷…雨湿花 2022-09-26 12:31:24

good job...

三生路 2022-09-26 12:31:24

收藏先,汇编也快忘了……

水水月牙 2022-09-26 12:31:24

好贴

咆哮 2022-09-26 12:31:24

very clear

自演自醉 2022-09-26 12:31:24

下面这些代码是什么意思哟
        .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

污味仙女 2022-09-26 12:31:24

原帖由 skybyte 于 2009-1-15 15:29 发表
下面这些代码是什么意思哟
        .long        .LASFDE1-.Lframe1
        .long        .LFB2
        .long        .LFE2-.LFB2
        .uleb128 0x0
        .byte        0x4
        .long      ...

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

ぽ尐不点ル 2022-09-26 12:31:24

没有人把这样的好帖做成精华帖啊。有点可惜啊。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文