Member Avatar for Member #866461

pushl %ebp
movl %esp,%ebp
pushl %ebx
movl 8(%ebp),%ebx
leal 2(%ebx),%edx
xorl %ecx,%ecx
cmpl %ebx,%ecx
jge .L4
.L6:
leal 5(%ecx,%edx),%edx
leal 3(%ecx),%eax
imull %eax,%edx
incl %ecx
cmpl %ebx,%ecx
jl .L6
.L4:
movl %edx,%eax
popl %ebx
movl %ebp,%esp
popl %ebp
ret

trying to make code in c then compiling it with the -S -m32 flags to see if i get the same output in the assemble file but its kind of confusing


its supposed to look something like this

int func(int x)
{
int i;
int result = _____________;
for( ________; ________; i++ ) {
__________________;
__________________;
}
return result;

}

Dani AI

Generated

Short summary: is on the right track — the assembly implements a simple accumulator loop that starts from a small offset of the input and iterates a fixed number of times. The key behavioral points to keep in mind are that the loop is conditional (it is skipped when the argument is non‑positive) and each iteration first increases the accumulator and then multiplies it by (i+3). That ordering matters for the result.

Practical tips for reproducing the same assembly (useful when you’re comparing your C to the .s output): compile with no optimizations and keep the frame pointer so the compiler emits the same prologue/epilogue you see. For example, generate assembly with gcc -m32 -O0 -fno-omit-frame-pointer -S file.c. Different optimization levels, different compilers, or different compiler versions will change register allocation and instruction selection, so exact instruction-by-instruction matches require the same toolchain and flags.

A few subtle points not shown explicitly in the thread:

  • EBX/ECX/EDX are being used as persistent variables and a counter; the compiler pushes EBX because it’s a callee‑saved register on 32‑bit x86.
  • The code uses LEA for additions (cheap address arithmetic that doesn’t touch flags) and IMUL for the multiply; that’s a common compiler pattern.
  • Repeated multiplication grows very fast. On 32‑bit signed ints that can overflow — signed overflow in C is undefined behavior. If you need predictable wrap or larger range, use unsigned types or a 64‑bit signed type.

If you want an exact mapping for study, compile with the flags above, examine the .s and the assembled binary (objdump -d) and iterate: small changes to the C (or adding volatile/explicit temporaries) help force the compiler to keep values in specific registers during learning experiments.

to convert your code to C, firstly you need to separate your code
- you have function so there are some part are common to all function
- if you have parameter you have code like 8(%ebp) or C(%ebp)
- and then try to translate each line to C then combine them

here I explain your asm code

pushl %ebp		; #start of call
movl %esp,%ebp	        ; #
pushl %ebx              ; backup ebx

movl 8(%ebp),%ebx       ; mov first parameter to ebx
leal 2(%ebx),%edx       ; result (edx) = first param + 2
xorl %ecx,%ecx          ; i = 0 (ecx as a for counter)
cmpl %ebx,%ecx          ; check i with first parameter
jge .L4                 ; if greater or equal to first param jump .L4
.L6:
leal 5(%ecx,%edx),%edx  ; result = result + i + 5
leal 3(%ecx),%eax       ; eax = i + 3 (used in the next instruction)
imull %eax,%edx         ; result = result * (i + 3)
incl %ecx               ; i++ (increment for counter)
cmpl %ebx,%ecx          ; check i with first parameter
jl .L6	                ; if less jump to .L6
.L4:

movl %edx,%eax         ; return result

popl %ebx              ; restor ebx
movl %ebp,%esp         ; #end of calling
popl %ebp              ; #
ret                    ; #

and converted to C can be something like this

int func(int x)
{
	int i;
	int result = x + 2;

	for (i = 0; i < x; i++){
		result = result + i + 5;
		result = result * (i + 3);
	}
	return result;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.