在IA32架构下,使用Ubuntu 12.04和gcc 4.6.3编译C文件和使用存储在.bss段上的汇编文件时,我遇到了一个问题,其中包括.comm和.lcomm指令。
在.comm和.lcomm缓冲区之间,汇编文件foo.s几乎使用了gas在该段中允许我分配的最大空间(foo计算long longs的质因数)。使用处理输入/输出等操作的汇编文件bar.s,一切都可以成功编译链接(而且速度很快),并且工作正常。
然后我使用C文件bar.c来处理输入/输出,gcc不会终止——至少不会在5分钟内终止。.bss请求接近于我的小笔记本内存,但由于.bss段在编译时不会被初始化,并且它可以与bar.s一起工作,所以我不知道为什么会出现这种情况。
当我减少foo.s中请求的.bss大小时,gcc可以成功编译链接,并且所有内容都可以正常执行。此外,如预期的那样,在每种情况下创建的可执行文件的文件大小都相同。
gcc bar.c foo.s -Wall
不依赖于在.bss中所请求的大小(我编译了各种大小,但它们都比原始大小小得多,失败了)。在所有情况下,可执行文件非常小(可能是10k)-实际上,除了原始情况外,全部大小都相同 - 但显然,原始情况无法成功编译并卡住。
这是gcc的错误吗?有没有命令行选项可以防止这种情况发生?或者到底发生了什么?
编辑:根据评论,这里是.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
.bss
部分,以便它最终在您的笔记本上翻页?当您仅使用汇编语言时,可能会避免运行时对.bss
的初始化。 - Michael Burr