【问题标题】:Assembly version of c program on gcc version 4.6.3gcc 版本 4.6.3 上 c 程序的汇编版本
【发布时间】:2016-05-01 00:12:06
【问题描述】:

我用c写了一个小数组程序

#include <stdio.h>
int main()
{
    int arr[]={1,2,3,4,5};//int size is 4, elements 5 so size of array = 4*5 = 20
    printf("%d\n", sizeof(arr));
    return 0;
}

我用

编译了这个
gcc -O2 -fverbose-asm -S -c arr_n_pointer_confusion.c 

我明白了,

    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "%d\n"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB22:
    .cfi_startproc
    pushl   %ebp    #
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp  #,
    .cfi_def_cfa_register 5
    andl    $-16, %esp  #,
    subl    $16, %esp   #,
    movl    $20, 8(%esp)    #,
    movl    $.LC0, 4(%esp)  #,
    movl    $1, (%esp)  #,
    call    __printf_chk    #
    xorl    %eax, %eax  #
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE22:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

任何人都可以将 C 中的汇编步骤联系起来。为什么我要这样做是为了了解一点汇编代码,以便我可以理解指针到数组的区别。

【问题讨论】:

  • 有什么问题?如您所见,数组的大小为 20,编译器也是如此。所以它打印 20。没有执行任何指令来达到这个数字。
  • 我一直对字符串、数组和指针感到困惑。这就是为什么我想学习 gcc 的汇编。一旦我知道生成的常用汇编代码,我自己就能理解其中的区别。
  • 在深入研究机器代码之前,您应该修复您的 C。 sizeof表达式的类型为size_t,需要格式化为%zu。将其传递给 %d 会导致未定义的行为。
  • @KerrekSB 我也用过 -Wall,没有看到任何警告。

标签: c arrays pointers assembly


【解决方案1】:

基本上,因为编译器在编译时就知道数组的内容,所以它可以删除数组,只需将sizeof(array) 替换为 20,而不必在运行时实际初始化数组。

.cfi_startproc
pushl   %ebp    # Save the value of ebp (points to the base of the stack) in the stack
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl    %esp, %ebp  #, Set the value of the base of the stack to the top of it
.cfi_def_cfa_register 5
andl    $-16, %esp  # Align the stack with a 16-byte boundary, used for SIMD instructions
subl    $16, %esp   # Subtract 16 from the value of the stack pointer (reserving 16 bytes of space for the stack)
movl    $20, 8(%esp)    # Set the memory 8 bytes above the stack as '20'
movl    $.LC0, 4(%esp)  # Move the string "%d\n" 4 bytes above the stack
movl    $1, (%esp)  # Set the flag for __printf_chk() to 1, enabling stack overflow checks
call    __printf_chk    # Print our string
xorl    %eax, %eax # Zero out the eax register (i.e. store the return code in eax, which is 0)

。 所以传递给__printf_chk的参数是(1, "%d\n", 20)。

【讨论】:

    【解决方案2】:

    使用gcc -g -fverbose-asm -S arr_n_pointer_confusion.c 编译。然后编译器添加.loc 伪语句,这些语句引用源文件中的行号。然后,您可以轻松地将汇编源代码与 C 代码相关联。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2020-01-18
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多