+ -
当前位置:首页 → 问答吧 → IA64,SUSE10,生成汇编语言的奇怪问题

IA64,SUSE10,生成汇编语言的奇怪问题

时间:2010-06-22

来源:互联网

本帖最后由 yulihua49 于 2010-06-22 16:00 编辑
  1. sdbc@jgbticket:~/rsa> cat mula.c
  2. mula(long a,long b,long c[2])
  3. {
  4. long d;
  5.         d=a*b;
  6.         c[0]=d;
  7. }
  8. sdbc@jgbticket:~/rsa> cc -m32 -S mula.c
  9. sdbc@jgbticket:~/rsa> cat mula.s
  10.         .file   "mula.c"
  11.         .text
  12. .globl mula
  13.         .type   mula, @function
  14. mula:
  15.         pushl   %ebp
  16.         movl    %esp, %ebp
  17.         subl    $16, %esp
  18.         movl    8(%ebp), %eax
  19.         imull   12(%ebp), %eax
  20.         movl    %eax, -4(%ebp)
  21.         movl    16(%ebp), %edx
  22.         movl    -4(%ebp), %eax
  23.         movl    %eax, (%edx)
  24.         leave
  25.         ret
  26.         .size   mula, .-mula
  27.         .ident  "GCC: (GNU) 4.1.2 20070115 (prerelease) (SUSE Linux)"
  28.         .section        .note.GNU-stack,"",@progbits
  29. sdbc@jgbticket:~/rsa> cc -S mula.c
  30. sdbc@jgbticket:~/rsa> cat mula.s
  31.         .file   "mula.c"
  32.         .text
  33. .globl mula
  34.         .type   mula, @function
  35. mula:
  36. .LFB2:
  37.         pushq   %rbp
  38. .LCFI0:
  39.         movq    %rsp, %rbp
  40. .LCFI1:
  41.         movq    %rdi, -24(%rbp)
  42.         movq    %rsi, -32(%rbp)
  43.         movq    %rdx, -40(%rbp)
  44.         movq    -24(%rbp), %rax
  45.         imulq   -32(%rbp), %rax
  46.         movq    %rax, -8(%rbp)
  47.         movq    -40(%rbp), %rdx
  48.         movq    -8(%rbp), %rax
  49.         movq    %rax, (%rdx)
  50.         leave
  51.         ret
  52. .LFE2:
  53.         .size   mula, .-mula
  54.         .section        .eh_frame,"a",@progbits
  55. .Lframe1:
  56.         .long   .LECIE1-.LSCIE1
  57. .LSCIE1:
  58.         .long   0x0
  59.         .byte   0x1
  60.         .string "zR"
  61.         .uleb128 0x1
  62.         .sleb128 -8
  63.         .byte   0x10
  64.         .uleb128 0x1
  65.         .byte   0x3
  66.         .byte   0xc
  67.         .uleb128 0x7
  68.         .uleb128 0x8
  69.         .byte   0x90
  70.         .uleb128 0x1
  71.         .align 8
  72. .LECIE1:
  73. .LSFDE1:
  74.         .long   .LEFDE1-.LASFDE1
  75. .LASFDE1:
  76.         .long   .LASFDE1-.Lframe1
  77.         .long   .LFB2
  78.         .long   .LFE2-.LFB2
  79.         .uleb128 0x0
  80.         .byte   0x4
  81.         .long   .LCFI0-.LFB2
  82.         .byte   0xe
  83.         .uleb128 0x10
  84.         .byte   0x86
  85.         .uleb128 0x2
  86.         .byte   0x4
  87.         .long   .LCFI1-.LCFI0
  88.         .byte   0xd
  89.         .uleb128 0x6
  90.         .align 8
  91. .LEFDE1:
  92.         .ident  "GCC: (GNU) 4.1.2 20070115 (prerelease) (SUSE Linux)"
  93.         .section        .note.GNU-stack,"",@progbits
复制代码
2-7行是一个简单的C函数。

第8行,按32位生成汇编。
10-28行是生成的32位汇编语言,完全没有问题。
29行,按照64位进行汇编。
31-93行是64位汇编。
对比32位汇编,发现17行,32位汇编在栈里预留了局部变量$16,虽然大了点但没问题。
在64位代码里,没有发现预留局部变量的指令。
18行,movl    8(%ebp), %eax; 从堆栈帧取自变量a。
而41行,64位代码,从寄存器取得自变量,暂存到局部变量区,而局部变量区并未分配。(%rsp没有动作),它为什么能正确工作呢?
我故意定义了一个局部变量,可以看到分别在22,48行使用了这个局部变量。
准备为大数乘法写个64位的高效算法:64bit × 64bit  = 128bit,弄不懂这个问题,写不下去了。
请高人解答,普罗大众可以热烈讨论。

作者: yulihua49   发布时间: 2010-06-22

好像只有青蛙做过IA64吧。

作者: prolj   发布时间: 2010-06-22

不懂IA64位汇编

作者: hellioncu   发布时间: 2010-06-22

  1. void mula(long a, long b, long c[2])
  2. {
  3.     long d;

  4.     d = a * b;
  5.     c[0] = d;
  6. }

  7. int main(int argc, char *argv[])
  8. {
  9.     long a, b, c[2];

  10.     a = 0x000000010000000a;
  11.     b = 0x000000020000000b;
  12.     mula(a, b, c);
  13. }

  14. stack:
  15. rbp - 40: [c array address]
  16. rbp - 32: [b value        ]
  17. rbp - 24: [a value        ]
  18. rbp - 16: [not use        ]
  19. rbp -  8: [d vaule        ]
  20. rbp     : [rbp value      ]
  21. rbp +  8: [return address ]

  22.     .file   "mula.c"
  23.     .text
  24. .globl mula
  25.     .type   mula, @function
  26. mula:
  27. .LFB2:
  28.     pushq   %rbp                ; push stack rbp (8 bytes)
  29. .LCFI0:
  30.     movq    %rsp, %rbp          ; rbp = rsp
  31. .LCFI1:
  32.     movq    %rdi, -24(%rbp)     ; a = rdi
  33.     movq    %rsi, -32(%rbp)     ; b = rsi
  34.     movq    %rdx, -40(%rbp)     ; c = rdx
  35.     movq    -24(%rbp), %rax     ; rax = a
  36.     imulq   -32(%rbp), %rax     ; rax = rax * b
  37.     movq    %rax, -8(%rbp)      ; d = rax
  38.     movq    -40(%rbp), %rdx     ; rdx = c
  39.     movq    -8(%rbp), %rax      ; rax = d
  40.     movq    %rax, (%rdx)        ; c[0] = d
  41.     leave
  42.     ret
  43. .LFE2:
  44.     .size   mula, .-mula
  45. .globl main
  46.     .type   main, @function
  47. main:
  48. .LFB3:
  49.     pushq   %rbp
  50. .LCFI2:
  51.     movq    %rsp, %rbp
  52. .LCFI3:
  53.     subq    $64, %rsp
  54. .LCFI4:
  55.     movl    %edi, -36(%rbp)
  56.     movq    %rsi, -48(%rbp)
  57.     movl    $10, -16(%rbp)      ; low  a = 0x0000000a
  58.     movl    $1, -12(%rbp)       ; high a = 0x00000001
  59.     movl    $11, -8(%rbp)       ; low  b = 0x0000000b
  60.     movl    $2, -4(%rbp)        ; high b = 0x00000002
  61.     leaq    -32(%rbp), %rdx     ; rdx = c
  62.     movq    -8(%rbp), %rsi      ; rsi = b
  63.     movq    -16(%rbp), %rdi     ; rdi = a
  64.     call    mula                ; call func, push stack return address (8 bytes)
  65.     leave
  66.     ret
  67. .LFE3:
  68.     .size   main, .-main
  69.     .section    .eh_frame,"a",@progbits
  70. .Lframe1:
  71.     .long   .LECIE1-.LSCIE1
  72. .LSCIE1:
  73.     .long   0x0
  74.     .byte   0x1
  75.     .string "zR"
  76.     .uleb128 0x1
  77.     .sleb128 -8
  78.     .byte   0x10
  79.     .uleb128 0x1
  80.     .byte   0x3
  81.     .byte   0xc
  82.     .uleb128 0x7
  83.     .uleb128 0x8
  84.     .byte   0x90
  85.     .uleb128 0x1
  86.     .align 8
  87. .LECIE1:
  88. .LSFDE1:
  89.     .long   .LEFDE1-.LASFDE1
  90. .LASFDE1:
  91.     .long   .LASFDE1-.Lframe1
  92.     .long   .LFB2
  93.     .long   .LFE2-.LFB2
  94.     .uleb128 0x0
  95.     .byte   0x4
  96.     .long   .LCFI0-.LFB2
  97.     .byte   0xe
  98.     .uleb128 0x10
  99.     .byte   0x86
  100.     .uleb128 0x2
  101.     .byte   0x4
  102.     .long   .LCFI1-.LCFI0
  103.     .byte   0xd
  104.     .uleb128 0x6
  105.     .align 8
  106. .LEFDE1:
  107. .LSFDE3:
  108.     .long   .LEFDE3-.LASFDE3
  109. .LASFDE3:
  110.     .long   .LASFDE3-.Lframe1
  111.     .long   .LFB3
  112.     .long   .LFE3-.LFB3
  113.     .uleb128 0x0
  114.     .byte   0x4
  115.     .long   .LCFI2-.LFB3
  116.     .byte   0xe
  117.     .uleb128 0x10
  118.     .byte   0x86
  119.     .uleb128 0x2
  120.     .byte   0x4
  121.     .long   .LCFI3-.LCFI2
  122.     .byte   0xd
  123.     .uleb128 0x6
  124.     .align 8
  125. .LEFDE3:
  126.     .ident  "GCC: (Debian 4.3.2-1.1) 4.3.2"
  127.     .section    .note.GNU-stack,"",@progbits
复制代码

作者: guoruimin   发布时间: 2010-06-22

这个是x86_64或者叫amd64,不是ia64。要安腾处理器的汇编码才是IA64。

作者: 没本   发布时间: 2010-06-22

rsp没有加是因为你的函数mula()内没有对别的函数的调用,编译器知道后,就没必要调整rsp了,节省一条指令,退出时用了leave指令,栈框不会出问题。
在x86_64下的rsp调整规范是,由调用者(caller)来处理栈指针而不是由被调用者(callee)来处理,因此编译器拥有这方面的完备信息,可以按情况处理。你加一个嵌套调用就能看到编译器调整rsp了,gcc会用(subq    $40, %rsp)。

作者: 没本   发布时间: 2010-06-22

本帖最后由 yulihua49 于 2010-06-22 20:39 编辑


QUOTE:
rsp没有加是因为你的函数mula()内没有对别的函数的调用,编译器知道后,就没必要调整rsp了,节省一条指令, ...
没本 发表于 2010-06-22 19:57




    高人。看到了。看来系统栈与应用栈是绝对分离的,其中不会因中断冲毁应用数据。

明白了。IA_64与X86_64还是有区别的。

作者: yulihua49   发布时间: 2010-06-22

从x86和x86_64的Linux和Windows WRK源码来看,系统栈和应用栈是分离的。

作者: 没本   发布时间: 2010-06-22

本帖最后由 yulihua49 于 2010-06-22 20:43 编辑


QUOTE:
不懂IA64位汇编
hellioncu 发表于 2010-06-22 16:26




    简单啊,eax变成rax就是64位的了。
就是函数自变量改寄存器传送了,可能是编译器的区别吧,但这样,不同编译器产生的模块不能互相连接了。是否能用
__stdc__ 声明标准栈调用呢?

作者: yulihua49   发布时间: 2010-06-22

本帖最后由 没本 于 2010-06-22 21:09 编辑

64位下的调用约定规范是AMD/Intel制定的,参数个数依次是:RCX, RDX, R8, R9, 栈。。。。。。, 调整RSP时,要把RCX..R9寄存器的栈空间也留出来,也就是几个参数就要几个参数的栈空间,不管是不是用的寄存器。不过GCC会优化,如果调用的函数没有下一层调用时,RSP不会变。

有兴趣可以看看段教学视频(英语字幕,Windows x64的):http://www.woodmann.com/TiGa/videos/TiGa-vid5.htm

作者: 没本   发布时间: 2010-06-22



QUOTE:
64位下的调用约定规范是Intel制定的,参数个数依次是:RCX, RDX, R8, R9, 栈。。。。。。, 调整RSP时,要把 ...
没本 发表于 2010-06-22 20:55




    学习了!

作者: yulihua49   发布时间: 2010-06-22

本帖最后由 guoruimin 于 2010-06-22 22:11 编辑
  1. /*---------- main.c ----------*/
  2. #include <stdio.h>

  3. void mula(long a, long b, long c[2]);

  4. int main(int argc, char *argv[])
  5. {
  6.     long a, b, c[2];

  7.     a = 0x12345678a;
  8.     b = 0x12345678b;
  9.     mula(a, b, c);

  10.     printf("%016lx%016lx\n", c[1], c[0]);

  11.     return 0;
  12. }

  13. /*---------- mula.c ----------*/
  14. void mula(long a, long b, long c[2])
  15. {
  16.     c[0] = a * b;
  17. }

  18. /*---------- mula.S ----------*/
  19.     .file   "mula.c"
  20.     .text
  21.     .p2align 4,,15
  22. .globl mula
  23.     .type   mula, @function
  24. mula:
  25. .LFB2:
  26. /*
  27. *  imulq   %rdi, %rsi
  28. *  movq    %rsi, (%rdx)
  29. */
  30.     /* replace with */
  31.     movq    %rdi, %rax          /* rax = a */
  32.     movq    %rdx, %rdi          /* rdi = c */
  33.     imulq   %rsi                /* rdx:rax = rax * b */
  34.     movq    %rax, (%rdi)        /* c[0] = rax */
  35.     movq    %rdx, 8(%rdi)       /* c[1] = rdx */

  36.     ret
  37. .LFE2:
  38.     .size   mula, .-mula
  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.     .align 8
  66. .LEFDE1:
  67.     .ident  "GCC: (Debian 4.3.2-1.1) 4.3.2"
  68.     .section    .note.GNU-stack,"",@progbits
复制代码
gcc -O2 -S mula.c -o mula.S
优化过的汇编代码,根本就没有用 rsp, rbp。
修改一下 mula.S,如上。
gcc main.c mula.S -o mula
./mula
00000000000000014b66dc35d989bdee

作者: guoruimin   发布时间: 2010-06-22

回复 没本


那是 windows 下的 Calling convention,不是 amd 所定义的。windows 是没有遵循 amd 的规定
amd 所定义的 AMD64 ABI 在:http://www.x86-64.org/documentation/abi-0.99.pdf

AMD64 ABI 所定义的是:
1、7个通用寄存器(rdi,rsi,rdx,rcx,r8,r9 和 rax)依次用作函数传递参数。
2、rsp 及 rbp 用于管理堆栈
3、r10 及 r11 用于临时寄存器
4、5个通用寄存器(r12,r13,r14,r15 及 rbx)由被调用方保存

作者: mik   发布时间: 2010-06-22

是的,我搞错了,那是Windows x64的stdcall调用约定。

作者: 没本   发布时间: 2010-06-22

windows 的 Calling convention 在一篇文章介绍:

http://msdn.microsoft.com/en-us/library/ms235286.aspx

作者: mik   发布时间: 2010-06-22