在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
答案 0 :(得分:2)
我在Debian上用gcc 4.7.2复制了你的问题。它并不适合我,但它需要相当长的时间(10秒)。
链接器似乎实际分配并且为#&#34; comm&#34;在它处理期间的记忆。如果机器有足够的内存限制(因为它似乎是你的),这将导致链接器抖动交换,即使最终的可执行文件很小。对我来说,内存分配大约是2.3Gb。
我尝试了几种变体(.space,.zero,.org),它们似乎都有同样的效果。
使用编译器(4.9)上的最新版本,这不再发生。