title: Force GCC to push arguments on the stack before calling function (using PUSH instruction)
body: <p>I have started developing a small 16-bit OS under GCC/G++.
  I am using a GCC cross-compiler, which I compiled under Cygwin, I am putting asm(&quot;.code16gcc\n&quot;) as the first line of each .CPP file, using Intel ASM syntax and the command lines for compiling and linking a .CPP file look like this:</p>
  <pre><code>G++: i586-elf-g++ -c $(CPP_FILE) -o $(OBJECT_OUTPUT) -nostdinc -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fpermissive -masm=intel
  
  LD: i586-elf-ld -T $(LD_SCRIPT) $(OBJECT_OUTPUT) -o $(BINARY_OUTPUT)
  </code></pre>
  <p>The problem I am currently facing is the way GCC translates function-calling code into assembly.</p>
  <p>To be more specific, instead of using the PUSH instruction to pass the arguments, GCC &quot;calculates&quot; the offsets relative to ESP the arguments should be located at, and then uses the MOV instruction to write the stack manually.</p>
  <p>This is not beneficial for me, since I rely on the PUSH instruction in my assembly code. To illustrate my problem clearer, take these 2 functions:</p>
  <pre><code>void f2(int x);
  
  void f1(){
      int arg = 8;
      asm(&quot;mov eax, 5&quot;);  // note: super hacky unsafe use of GNU C inline asm
      asm(&quot;push eax&quot;);    // Writing registers without declaring a clobber is UB
      f2(arg);
      asm(&quot;pop eax&quot;);
  }
  void f2(int x){
  }
  </code></pre>
  <p>In function f1, I am saving EAX using the PUSH instruction, and I would expect to have it restored to 5 after calling f2 and executing the &quot;POP EAX&quot; instruction. It turns out however that EAX becomes 8, not 5. That's because the ASSEMBLY CODE GCC generates looks like this (I've included the source as well for clarity):</p>
  <pre><code>void f1()
  C++: {
      push ebp
      mov ebp,esp
      sub esp,byte +0x14
  
      C++: int arg = 8;
          mov dword [ebp-0x4],0x8
      
      C++: asm(&quot;mov eax, 5&quot;);
          mov eax,0x5
      
      C++: asm(&quot;push eax&quot;);
          push eax
      
      C++: f2(arg);
          mov eax,[ebp-0x4]
          mov [dword esp],eax =======&gt;&gt;&gt;&gt;&gt;&gt; HERE'S THE PROBLEM, WHY NOT 'PUSH EAX' ?!!
          call f2
          
      C++: asm(&quot;pop eax&quot;);
          pop eax
      
  C++: }
      o32 leave
      o32 ret
      
  void f2(int x)
  C++: {
      push ebp
      mov ebp,esp
  C++: }
      pop ebp
      o32 ret
  </code></pre>
  <p>I have tried using some G++ compilation flags like -mpush-args or -mno-push-args and another one which I can't remember and GCC still doesn't want to use PUSH. The version I'm using is <code>i586-elf-g++ (GCC) 4.7.2</code> (Cross-Compiler recompiled in Cygwin).</p>
  <p>Thank you in advance!</p>
  <p><strong>UPDATE</strong>: Here's a webpage I've found: <a href="http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html" rel="nofollow noreferrer">http://fixunix.com/linux/6799-gcc-function-call-pass-arguments-via-push.html</a></p>
  <p>That just seems really stupid for GCC to do, considering that it limits the usability of inline assembly for complex stuff. :( Please leave an answer if you have a suggestion.</p>