title: Why would g++ compiled code write beyond stack pointer?
body: <p>To better understand assembly, I compiled a simple C++ program using g++ and then used gdbgui to step through the execution.  I made a graphic of the state of the stack and registers at several  consecutive points in the program to help myself better understand exactly what was going on.  It appears that the program writes/reads at memory beyond the stack pointer several times during execution.  This surprised me.  I was under the impression that a program should never write beyond the stack pointer.  I understand how it works, the relative addressing is based off of the base pointer, but I would've expected the program to adjust the stack pointer in some way to encompass the memory it planned on using.  Is this method of writing beyond the stack a common technique for compilers?</p>
  
  <p>C++:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  int square(int i) {
      i = i * i;
      return i;
  }
  
  int main() {
      int i = square(2);
  }
  
  </code></pre>
  
  <p>Compiled on Ubuntu 19.10 with:</p>
  
  <pre><code>g++ -o square_2 square_2.cpp
  </code></pre>
  
  <p>g++ version:</p>
  
  <pre><code>g++ -v
  Using built-in specs.
  COLLECT_GCC=g++
  COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
  OFFLOAD_TARGET_NAMES=nvptx-none:hsa
  OFFLOAD_TARGET_DEFAULT=1
  Target: x86_64-linux-gnu
  Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.2.1-9ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
  Thread model: posix
  gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2) 
  </code></pre>
  
  <p>Relevant assembly from gdb:</p>
  
  <pre><code>0x55555555516d     push rbp
  0x55555555516e     mov rbp,rsp
  0x555555555171     mov DWORD PTR [rbp-0x4],edi
  0x555555555174     mov eax,DWORD PTR [rbp-0x4]
  0x555555555177     imul eax,eax
  0x55555555517a     mov DWORD PTR [rbp-0x4],eax
  0x55555555517d     mov eax,DWORD PTR [rbp-0x4]
  0x555555555180     pop rbp
  0x555555555181     ret 
  
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/TwUBf.png" rel="noreferrer">Execution Trace</a></p>
  
  <p>I used yellow highlighting to indicate when a value was updated, and green highlighting to show which memory contents the stack pointer is currently pointing at.</p>
  
  <p><a href="https://i.stack.imgur.com/fx61Q.png" rel="noreferrer">gdbgui screenshot</a></p>