From C textbooks you know that you can use function arguments just like local variables. Let's try.
First example:
#include <stdio.h> void f() { int x, y; for (x=0; x<3; x++) for (y=0; y<3; y++) printf ("%d %d\n", x, y); }; void main() { f(); };
Looks innocent! Let's rewrite it:
void f(int x, int y) { for (x=0; x<3; x++) for (y=0; y<3; y++) printf ("%d %d\n", x, y); }; void main() { f(0, 0); };
Works just like the first function.
Compile both for 32-bit x86 (you may need to install additional GCC deps):
gcc -S -masm=intel -m32 fname.c
Compare (diff) two assembly outputs (some lines omitted):
% diff -u v1.s v2.s ... mov ebp, esp push ebx - sub esp, 20 + sub esp, 4 call __x86.get_pc_thunk.bx add ebx, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_ - mov DWORD PTR -16[ebp], 0 + mov DWORD PTR 8[ebp], 0 jmp .L2 .L5: - mov DWORD PTR -12[ebp], 0 + mov DWORD PTR 12[ebp], 0 jmp .L3 .L4: sub esp, 4 - push DWORD PTR -12[ebp] - push DWORD PTR -16[ebp] + push DWORD PTR 12[ebp] + push DWORD PTR 8[ebp] lea eax, .LC0@GOTOFF[ebx] push eax call printf@PLT add esp, 16 - add DWORD PTR -12[ebp], 1 + add DWORD PTR 12[ebp], 1 .L3: - cmp DWORD PTR -12[ebp], 2 + cmp DWORD PTR 12[ebp], 2 jle .L4 - add DWORD PTR -16[ebp], 1 + add DWORD PTR 8[ebp], 1 .L2: - cmp DWORD PTR -16[ebp], 2 + cmp DWORD PTR 8[ebp], 2 jle .L5 ...
The only difference is that x/y variables are located on another side of ESP (stack pointer)!
In x64 that picture will be slightly different and somewhat harder to understand. This is why I used 32-bit code here in my example.
Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.