需要帮助理解GCC汇编代码



对于我的家庭作业,我应该转换这个C代码

 #define UPPER 15
 const int lower = 12;
 int sum = 0;
 int main(void) {
   int i;
   for (i = lower; i < UPPER; i++) {
     sum += i;
   }
   return sum;
 }

放入GCC程序集。我已经编译了它,以便在手工翻译之前先研究代码(显然手工翻译看起来会有很大不同)。这是我收到的汇编代码:

.file   "upper.c"
.globl  lower
.section    .rodata
.align 4
.type   lower, @object
.size   lower, 4
    lower:
.long   12
.globl  sum
.bss
.align 4
.type   sum, @object
.size   sum, 4
     sum:
.zero   4
.text
.globl  main
.type   main, @function
    main:
    .LFB0:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
movl    $12, -4(%rbp)
jmp .L2
    .L3:
movl    sum(%rip), %edx
movl    -4(%rbp), %eax
addl    %edx, %eax
movl    %eax, sum(%rip)
addl    $1, -4(%rbp)
    .L2:
cmpl    $14, -4(%rbp)
jle .L3
movl    sum(%rip), %eax
popq    %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
    .LFE0:
.size   main, .-main
.ident  "GCC: (SUSE Linux) 4.8.1 20130909 [gcc-4_8-branch revision 202388]"
.section    .note.GNU-stack,"",@progbits

现在我想知道是否有人可以给我一些例子,如

  • ,其中构造函数i, lower, upper和sum位于代码
  • ,其中一些表达式i = lower或i
  • for循环开始的地方

之类的东西,这样我就可以了解汇编代码是如何构造的。谢谢你!

如果我理解对了你的问题,下面是答案:

Q:构造函数i, lower, upper和sum在代码中的位置?

lower位于.rodata区(只读数据区)内。它的值在程序加载阶段由linux加载器初始化为值.long 12lower构造器是一个linux加载器。它只是从二进制图像中加载lower值。

.globl  lower
.section    .rodata
.align 4
.type   lower, @object
.size   lower, 4
    lower:
.long   12

sum位于.bss section(包含静态分配变量的数据段)内。它的值由_init函数初始化,该函数在程序执行开始时被调用。它的值是0 (.zero 4)。.bss节中的每个变量的初始值都为0(链接到wiki的.bss文章)。

.globl  sum
.bss
.align 4
.type   sum, @object
.size   sum, 4
     sum:
.zero   4

upper是一个常量。编译器没有将它的声明放入汇编中。这里有对upper-1(作为$14)的引用:

    .L2:
cmpl    $14, -4(%rbp)

i是一个栈上临时变量。它的值是使用相对%rbp的地址访问的(%rbp是指向当前函数堆栈帧的指针)。在汇编中没有显式地声明i。我认为i没有显式的堆栈保留(在main序言中没有sub $0x8,%rsp这样的指令),因为main不调用其他函数。下面是i初始化的代码(注意编译器知道lower的初始值是$12,并且在i初始化期间删除了对lower的访问):

movl    $12, -4(%rbp)

Q:其中一些表达式i = lower或i <</p>

i = lower:

movl    $12, -4(%rbp)
jmp .L2

i < UPPER:

    .L2:
cmpl    $14, -4(%rbp)
jle .L3

i++:

addl    $1, -4(%rbp)

sum += i;:

movl    sum(%rip), %edx
movl    -4(%rbp), %eax
addl    %edx, %eax
movl    %eax, sum(%rip)

return sum; (%eax寄存器用于保存函数返回值-更多关于此:X86调用约定):

jle .L3
movl    sum(%rip), %eax
popq    %rbp
.cfi_def_cfa 7, 8
ret

Q: for循环开始的位置

它从这里开始:

movl    $12, -4(%rbp)
jmp .L2

最新更新