Вызов функции C из сборки-приложение зависает при "вызове printf", и я понятия не имею, почему

Я буду работать над большим проектом сборки, но сейчас только начинаю изучать этот новый язык. Я пытаюсь сделать несколько простых примеров, таких как вы можете найти для c++ в старшей школе (сумма двух чисел, простое число и т. д.).

теперь я должен отобразить все простые числа до n. Проблема в том, что приложение зависает при "вызове printf", и я понятия не имею, почему.

вы можете помочь мне с этим?

.section    .data
prime_number_str:
.asciz  "%d "

.section    .text

.global     _start
_start:
pushl   
call .first_prime_numbers
addl , %esp
pushl 
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 , %esp       #restore the stack

#if not prime jump to the next number   
cmpl , %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 , %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 , %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 , %ebx       #assume the argument is prime
test_prime:
# if ecx == 1 then return exit the function
cmpl , %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 , %edx   
popl %eax       #restore the value of eax   
je not_prime


subl , %ecx       #decrease counter
jmp test_prime      #try next division

not_prime:
movl , %ebx
return_value:
movl %ebx, %eax
ret 

3 ответов


это, вероятно, потому, что ваши регистры все перепутались после вызова printf, вам нужно сохранить регистры, которые вы обычно используете после printf а затем восстановить их после вызова.

это то, что вы должны делать всегда, когда вы делаете syscall или другие вызовы, которые могут повлиять на ваши регистры.

также вы должны смотреть на gdb (GNU debugger ) похоже, что вы кодируете GAS, поэтому, если вы находитесь в системе gnu / linux, попробуйте:

gdb youprogram

и затем запустите его, чтобы увидеть, где происходит сбой.


еще одна проблема заключается в том, что вы неправильно очищаете стек после вызова printf. Вам нужно добавить 8 в ESP, потому что вы нажали ECX (4 байта) и адрес (4 байта в 32-битном режиме).

также обратите внимание, что, по крайней мере, в Windows (с помощью MinGW), printf топает по EAX (возвращаемое значение), ECX и EDX и изменяет EFLAGS. Как и все стандартные функции C, которые я использовал до сих пор, по этому вопросу.


также обратите внимание, что в C/C++ вам нужно выскочить из регистров самостоятельно (например, в Pascal calling convertion процедура выдает "ret 8").