我将参与一个大型的大会项目,但现在才开始学习这种新语言。我正在尝试制作一些简单的例子,比如你可能在highschool中找到c ++(总和两个数字,是数字素数等)。
现在我必须显示最多n的所有素数。问题是应用程序冻结在“call printf”,我不明白为什么。
你能帮我解决这个问题吗?
.section .data
prime_number_str:
.asciz "%d "
.section .text
.global _start
_start:
pushl $20
call .first_prime_numbers
addl $4, %esp
pushl $0
call exit
.first_prime_numbers: #argument first n numbers
movl 4(%esp), %ecx #get the first argument
do_test:
pushl %ecx #push function arguments
call .prime
addl $4, %esp #restore the stack
#if not prime jump to the next number
cmpl $0, %eax
je no_not_prime
#print the number
pushl %eax #save eax
pushl %ecx #first argument
pushl $prime_number_str #text to print
call printf
addl $4, %esp
popl %eax #restore eax
no_not_prime:
loop do_test
ret
.prime: #argument: number to check
movl 4(%esp), %eax #get the first argument
#divide the argument by 2
xorl %edx, %edx
movl $2, %ecx
pushl %eax #save the value of eax
divl %ecx
movl %eax, %ecx #init the counter register
popl %eax #restore the value of eax
movl $1, %ebx #assume the argument is prime
test_prime:
# if ecx == 1 then return exit the function
cmpl $1, %ecx
jle return_value
pushl %eax #save the old value of eax
#divide the value by the value of counter
xorl %edx, %edx
divl %ecx
#if the reminder is 0 then the number is not prime
cmpl $0, %edx
popl %eax #restore the value of eax
je not_prime
subl $1, %ecx #decrease counter
jmp test_prime #try next division
not_prime:
movl $0, %ebx
return_value:
movl %ebx, %eax
ret
答案 0 :(得分:4)
可能是因为你的寄存器在调用printf
之后都被搞砸了,你需要在printf
之后保存你倾向于使用的寄存器,然后在调用之后恢复它们。
这是您应该做的事情syscall
或其他可能会篡改您的注册的电话。
另外你应该看看gdb
(gnu调试器)看起来你正在编写GAS,所以如果你在gnu / linux系统上试试:
gdb youprogram
然后运行它以查看它失败的位置。
答案 1 :(得分:2)
另一个问题是,在调用printf之后,您没有正确清理堆栈。您需要向ESP添加8,因为您按下了ECX(4字节)和一个地址(32位模式下为4字节)。
另外,请注意,至少在Windows上(使用MinGW),printf会在EAX(返回值),ECX和EDX上进行踩踏,并修改EFLAGS。就像我迄今为止使用的所有标准C函数一样。
答案 2 :(得分:1)
请注意,在C / C ++中你需要自己弹出寄存器(在Pascal调用转换中,例如程序发出“ret 8”)。