Calling a C function from Assembly - the application freezes when calling printf, and I have no idea why

I will be working on a large Assembly project, but now I'm just starting to learn this new language. I am trying to make some simple examples, for example, you can find for C ++ in highschool (the sum of two numbers, the number of primes, etc.).

Now I need to display all primes up to n. The problem is that the application freezes when printf is called, and I have no idea why.

Can you help me?

.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 
+6
assembly printf
source share
3 answers

Probably because your registers are confused after calling printf , you need to save the registers that you usually use after printf , and then restore them after the call.

This is what you should do whenever you syscall or other calls that may violate your registers.

You should also look into gdb (the gnu debugger) looks like you are encoding GAS, so if you are on a gnu / linux system, try:

 gdb youprogram 

and then run it to see where it doesn’t work.

+4
source share

Another problem is that you are not clearing the stack after calling printf. You need to add 8 to ESP because you pressed ECX (4 bytes) and address (4 bytes in 32-bit mode).

Also note that, at least on Windows (using MinGW), printf stomps on EAX (return value), ECX and EDX and modifies EFLAGS. Like all standard C functions that I have used so far, in this regard.

+2
source share

Also note that in C / C ++ you need to pull the registers yourself (in the conversion of a Pascal call, for example, the procedure calls "ret 8").

+1
source share

All Articles