title: setjmp and longjmp implementation
body: <p>basically my problem in short is my implementation for setjmp and longjmp 
  doesn't work. the reason why i'm asking in this form not in (code review) is that i'm new to assembly i've little background and still learning but still not sure about the code (please read until the end). </p>
  
  <p>first i'v executed the code on two platforms with three different compilers 
  and that's the reason why i'm sure that i'm doing something wrong with the assembler.</p>
  
  <p>platforms: mac OS 10.12.5 x86_64 , ubuntu linux x86
  compilers: Apple LLVM clang 8.0.0 x86_x64 ,clang 3.9.1 x86_x64 ,gcc 6.3 x86</p>
  
  <p>i've compiled the code in 32bit mode on all platforms so the generated machine code on linux and mac with this example is 32bit.</p>
  
  <p>the code i will post here is the was compiled under Apple clang with no optimization using -m32 flag to generate 32bit machine code </p>
  
  <pre><code> #include &lt;cstdio&gt;
  
  
  typedef unsigned long jmp_buf[6];
  
  
  int Setjmp(jmp_buf var){
       __asm__(
               "    mov -4(%ebp), %eax     # get pointer to jmp_buf, passed as argument on stack\n"
               "    mov    %ebx, (%eax)   # jmp_buf[0] = ebx\n"
               "    mov    %esi, 4(%eax)  # jmp_buf[1] = esi\n"
               "    mov    %edi, 8(%eax)  # jmp_buf[2] = edi\n"
               "    mov    %ebp, 12(%eax) # jmp_buf[3] = ebp\n"
               "    lea   4(%esp), %ecx     # get previous value of esp, before call\n"
               "    mov    %ecx, 16(%eax) # jmp_buf[4] = esp before call\n"
               "    mov  (%esp), %ecx     # get saved caller eip from top of stack\n"
               "    mov    %ecx, 20(%eax) #jmp_buf[5] = saved eip\n"
               "    xor    %eax, %eax     #eax = 0\n"
       );
  
      return 0;
  }
  
  void Longjmp(jmp_buf var,int m){
      __asm__("    mov  -4(%ebp),%edx # get pointer to jmp_buf, passed as argument 1 on stack\n"
              "    mov  -8(%ebp),%eax #get int val in eax, passed as argument 2 on stack\n"
              "    test    %eax,%eax # is int val == 0?\n"
              "    jnz 1f\n"
              "    inc     %eax      # if so, eax++\n"
              "1:\n"
              "    mov   (%edx),%ebx # ebx = jmp_buf[0]\n"
              "    mov  4(%edx),%esi # esi = jmp_buf[1]\n"
              "    mov  8(%edx),%edi #edi = jmp_buf[2]\n"
              "    mov 12(%edx),%ebp # ebp = jmp_buf[3]\n"
              "    mov 16(%edx),%ecx # ecx = jmp_buf[4]\n"
              "    mov     %ecx,%esp # esp = ecx\n"
              "    mov 20(%edx),%ecx # ecx = jmp_buf[5]\n"
              "    jmp *%ecx         # eip = ecx");
  }
  
  
  
  void fancy_func(jmp_buf env);
  
  int main() {
      jmp_buf env;
      int ret = Setjmp(env);
      if (ret == 0) {
          puts("just returning from setjmp!");
          fancy_func(env);
      } else {
          puts("now returning from longjmp and exiting!");
      }
  
  }
  
  void fancy_func(jmp_buf env) {
      puts("doing fancy stuff");
      Longjmp(env, 1);
  }
  </code></pre>
  
  <p>i was following this tutorial : <a href="http://vmresu.me/blog/2016/02/09/lets-understand-setjmp-slash-longjmp/" rel="nofollow noreferrer">http://vmresu.me/blog/2016/02/09/lets-understand-setjmp-slash-longjmp/</a></p>
  
  <p>Note: I've debugged the source code the problem comes from the:</p>
  
  <pre><code> jmp *%ecx
  </code></pre>
  
  <p>but i think the problem is with setjmp and the way i'm storing the context 
  and specially that line: </p>
  
  <pre><code> lea   4(%esp), %ecx     # get previous value of esp, before call\n"
  </code></pre>
  
  <p>which is also the part of the code that i'm not getting it. </p>
  
  <p>i'm also aware of the code that was generated by my compiler for calling and cleaning the stack of setjmp and longjmp and the calling convention that was used (CDECL) in my case. </p>
  
  <p>much thanks for any help .</p>