954,479 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

printf in assembly

Hello all!

I am trying to complete a lab assignment for my computer systems class and we have to use the printf function to print changing register values (increment eax from 1 to 10, decrement ebx from 10 to 1).

Here is my code:

; Purpose: To print data to screen using printf
; Assemble: nasm -f elf -l printflab.lst printflab.asm
; Link: gcc -o printflab printflab.o


	extern printf		; The C function to be called

	section .data		; data section

fmt: db "eax=%d, ebx=%d", 10, 0 ; The printf format, "\n", '0'
	section .text		; code section

global main			; standard gcc entry point


main:				; program label for entry point

	mov ecx, 10		; set register ecx to value 10
	mov eax, 1		; set register eax to value 1	
	mov ebx, 10		; set register ebx to value 10 		

back1:				; loop label

	inc eax			; increment eax register
	dec ebx			; decrement ebx register
	push dword fmt		; address of ctrl string
	call printf		; Call C function
	loop back1		; loop until ecx = 0

endprog:			; exit the program

	mov esp, ebp		; takedown stack frame
	pop ebp			; same as "leave" op
	
	mov ebx, 0		; 0 = normal
	mov eax, 1		; 1 = no error
	int 0x80		; interrupt 80 hex, call kernel


After assembly and linking, the program just loops infinitely with the same number in both the eax and ebx registers. Am I missing something (like pushing the eax and ebx registers into the stack)?

Thanks in advance for your help

Idestruction
Newbie Poster
13 posts since Nov 2011
Reputation Points: 10
Solved Threads: 0
 

I recommend to push all necessary register before using external function. Add

push eax
push ebx
push ecx


before

call printf


and

pop ecx
pop ebx
pop eax


after it.

skaa
Light Poster
36 posts since Jan 2011
Reputation Points: 13
Solved Threads: 5
 

line 26: you are not pushing enough things before calling printf(). The format string you are using calls for two integers. You need to push those two integers as well as the format string.

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

Nothing seems to be working. I have tried doing as skaa said, but that did not help. It still loops infinitely... i know I am missing something, but I am new to assembly and we did not get to the printf section of our lecture in class.

EDIT:

Using GDB, I have found something weird, at least weird to me. When I single step through the back1 loop, the program comes to the printf call with all numbers correct. Single stepping into the printf function, control jumps to the function itself. This is normal, however, when the function is done, it single steps into something called ?? () from /lib/ld-linux.so.2. What is this and is it relevant? It will also not single step out of this weird function-like-thing, which is where the registers become corrupt and have wrong numbers stored in them.

Idestruction
Newbie Poster
13 posts since Nov 2011
Reputation Points: 10
Solved Threads: 0
 

1.I don't like this printf, i prefere use the library msvcrt.inc and use the crt_printf, remember that you need to push an offset not a DWORD..

2.You need to use 3 pushs in the printf because you need to move to the stack the first number, the second number and then the string...

3. I don't like to use this type of loop, i prefere the old CMP one, its just because it gets quicklier when the program is running

AceStryker
Light Poster
47 posts since Aug 2011
Reputation Points: 10
Solved Threads: 2
 

1.I don't like this printf, i prefere use the library msvcrt.inc and use the crt_printf, remember that you need to push an offset not a DWORD..

2.You need to use 3 pushs in the printf because you need to move to the stack the first number, the second number and then the string...

3. I don't like to use this type of loop, i prefere the old CMP one, its just because it gets quicklier when the program is running

#1: I have to use printf, that is what the assignment calls for.

#2: I tried pushing everything to the stack, it did not work.

#3: This is the only loop I know for NASM, as I have only been doing this for a few days

Idestruction
Newbie Poster
13 posts since Nov 2011
Reputation Points: 10
Solved Threads: 0
 

This was tested on VS C++ 2008:

char	fmt[]="eax=%d, ebx=%d\n";
_asm
{
	mov ecx, 8
	mov eax, 1
	mov ebx, 10

back1:
	inc eax
	dec ebx
	push	eax
	push	ebx
	push	ecx

	push	ebx
	push	eax
	lea	eax,fmt
	push	eax
	call dword ptr [printf]
	pop	eax
	pop	eax
	pop	eax

	pop	ecx
	pop	ebx
	pop	eax
	loop back1

	nop
}


. Working correctly.

skaa
Light Poster
36 posts since Jan 2011
Reputation Points: 13
Solved Threads: 5
 

What is the lea instruction? And how does that translate to NASM?

Idestruction
Newbie Poster
13 posts since Nov 2011
Reputation Points: 10
Solved Threads: 0
 
What is the lea instruction? And how does that translate to NASM?


there is no translation. It is a CPU mneumonic on x86 it means load effective address

GunnerInc
xor eax, eax
Team Colleague
79 posts since Jan 2011
Reputation Points: 38
Solved Threads: 13
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You