gcc用.s文件编译.c文件 - .bss混淆(bug?)

时间:2014-06-16 02:36:21

标签: c linux gcc assembly x86

在IA32架构上使用Ubuntu 12.04下的gcc 4.6.3,我遇到了一个问题,即使用带有.com和.lcomm指令的.bss段上的存储来编译带有汇编文件的C文件。

在.comm和.lcomm缓冲区之间,汇编文件foo.s使用接近最大空间气体让我在这个段中分配(foo计算long long的素数因子分解)。使用汇编文件bar.s处理i / o等,一切都编译和链接很好(和快速),并且运行良好。

当我使用C文件bar.c来处理i / o时,gcc不会终止 - 或者至少不会在5分钟内终止。 .bss请求接近我的小笔记本内存,但由于.bss段没有初始化编译时,并且因为它与bar.s一起使用,我不明白为什么会发生这种情况。

当我减少foo.s中请求的.bss大小时,gcc编译并链接正常,一切都按原样执行。此外,正如预期的那样,在每种情况下使用

创建的可执行文件的文件大小
   gcc bar.c foo.s -Wall      

不依赖于.bss请求的大小(我编译了不同的大小,这些大小都比原来的小,大小不合适)。在所有情况下,可执行文件都非常小(可能是10k) - 事实上,大小相同 - 除了显然原始情况,它没有成功编译并挂起。

这是一个gcc bug吗?是否有用于防止这种情况发生的命令行选项?或者发生了什么?

编辑:根据评论,这里是.bss段分配的部分:

# Sieve of Eratosthenes
# Create list of prime numbers smaller than n
#
# Note: - no input error (range) check
#       - n <= 500,000,000 (could be changed) - in assembly
#         compiling it with gcc: trouble. make n <= 50,000,000
# Returns: pointer to array of ints of prime numbers
#          (0 sentinel at end)
#
# Registers: %esi: sentinel value (n+1)
#            %edx: n
#            %ecx: counting variable (2 - n)
#            %ebx: pointer into array of primes
#                  (position next to be added)
#            %eax: inner pointer to A. tmp array
    .section .bss
#   .lcomm tmp_Arr, 2000000008  # 500,000,000 plus sentinel & padding
#   .comm prime_Arr, 500000008 # asymptotically, primes aren't dense
    .lcomm tmp_Arr, 200000008  # 50,000,000 plus sentinel & padding
    .comm prime_Arr, 50000008 # asymptotically, primes aren't dense

    .section .text
    .globl sieve
     .type sieve, @function
sieve:
    pushl %ebp
    movl %esp, %ebp
    movl 8(%ebp), %edx
    pushl %esi
    pushl %ebx  

    # create Eratosthenes tmp array
    movl $0, %ecx
loop_sieve_Tmp_:    
    movl %ecx, tmp_Arr(, %ecx, 4)
    addl $1, %ecx
    cmp %ecx, %edx
    jge loop_sieve_Tmp_

    # initialize registers used in algorithm
    movl $2, %ecx   # outer loop counting var
    movl %ecx, %eax # inner loop counting var
    xor %ebx, %ebx  # pointer to prime array
    movl %edx, %esi
    incl %esi       # sentinel (or placeholder for 'not prime')
 loop_sieve_Outer_:
    movl %ecx, prime_Arr(, %ebx, 4)  # record prime
    incl %ebx
 loop_sieve_Inner_:
    addl %ecx, %eax
    movl %esi, tmp_Arr(, %eax, 4)
    cmp %eax, %edx
    jge loop_sieve_Inner_
 find_Next_:    # find minimum in Erist. tmp array
    addl $1, %ecx
    cmp %ecx, %edx
    jl lbl_sieve_done_
    cmp tmp_Arr(, %ecx, 4), %esi
    je find_Next_

    movl %ecx, %eax
    jmp loop_sieve_Outer_
 lbl_sieve_done_:
    movl $0, prime_Arr(, %ebx, 4)       # sentinel
    movl $prime_Arr, %eax

    popl %ebx
    popl %esi
    movl %ebp, %esp
    popl %ebp
    ret
 # end sieve

1 个答案:

答案 0 :(得分:2)

我在Debian上用gcc 4.7.2复制了你的问题。它并不适合我,但它需要相当长的时间(10秒)。

链接器似乎实际分配并且为#&#34; comm&#34;在它处理期间的记忆。如果机器有足够的内存限制(因为它似乎是你的),这将导致链接器抖动交换,即使最终的可执行文件很小。对我来说,内存分配大约是2.3Gb。

我尝试了几种变体(.space,.zero,.org),它们似乎都有同样的效果。

使用编译器(4.9)上的最新版本,这不再发生。

相关问题