home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   soc.culture.quebec      More than just pale imitations of France      108,436 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 108,042 of 108,436   
   World-News2100 to All   
   More of my philosophy about setjmp() and   
   23 Nov 21 15:23:09   
   
   From: m1@m1.com   
      
   Hello..   
      
      
   More of my philosophy about setjmp() and longjmp() and generators and   
   coroutines..   
      
   I am a white arab from Morocco, and i think i am smart since i have also   
   invented many scalable algorithms and algorithms..   
      
   I have just quickly implemented setjmp() and longjmp() in x64 assembler,   
   and after that i have just implemented quickly a good example of a   
   generator with my setjmp() and longjmp(), look at it below, and in   
   computer science, a generator is a routine that can be used to control   
   the iteration behaviour of a loop. All generators are also iterators. A   
   generator is very similar to a function that returns an array, in that a   
   generator has parameters, can be called, and generates a sequence of   
   values. However, instead of building an array containing all the values   
   and returning them all at once, a generator yields the values one at a   
   time, which requires less memory and allows the caller to get started   
   processing the first few values immediately. In short, a generator looks   
   like a function but behaves like an iterator. So here is my   
   implementations in freepascal and delphi and they are working perfectly:   
      
   Here is my first unit that implement longjmp() and setjmp() and notice   
   how i am saving the non-volatile registers and how i am coding it in   
   x64 assembler:   
      
   ======   
      
      
   { Volatile registers: The calling program assumes registers   
   RAX, RCX, RDX, and R8 through R11 are volatile.   
   The contents of registers RBX, RSI, RDI, RBP, RSP, and   
   R12 through R15 are considered non-volatile. Functions return   
   values in RAX. }   
      
      
      
   unit JmpLib64;   
      
   {$IFDEF FPC}   
   {$ASMMODE intel}   
   {$ENDIF}   
   interface   
      
   type   
      jmp_buf = record   
        RBX,   
        RSI,   
        RDI,   
        RSP,   
        RBP,   
        RIP,   
        R12,   
        R13,   
        R14,   
        R15: UInt64;   
     end;   
      
   { setjmp captures the complete task state which can later be used to   
   perform a non-local goto using longjmp. setjmp returns 0 when it is   
   initially called,  and a non-zero value when it is returning from a call   
   to longjmp. setjmp must be called before longjmp. }   
      
   function  setjmp(out jmpb: jmp_buf): UInt64;   
      
   { longjmp restores the task state captured by setjmp (and passed in   
   jmpb). It then returns in such a way that setjmp appears to have   
   returned with the value retval. setjmp must be called before longjmp. }   
      
   procedure longjmp(const jmpb: jmp_buf; retval: UInt64);   
   implementation   
      
   function  setjmp(out jmpb: jmp_buf): UInt64; assembler;{$IFDEF FPC}   
   nostackframe; {$ENDIF}register;   
   asm   
   {     ->  RCX     jmpb   }   
   {     <-  RAX     Result }   
              MOV     RDX, [RSP]  // Fetch return address (RIP)   
              // Save task state   
              MOV     [RCX+jmp_buf.&RBX], RBX   
              MOV     [RCX+jmp_buf.&RSI], RSI   
              MOV     [RCX+jmp_buf.&RDI], RDI   
              MOV     [RCX+jmp_buf.&RSP], RSP   
              MOV     [RCX+jmp_buf.&RBP], RBP   
              MOV     [RCX+jmp_buf.&RIP], RDX   
              MOV     [RCX+jmp_buf.&R12], R12   
              MOV     [RCX+jmp_buf.&R13], R13   
              MOV     [RCX+jmp_buf.&R14], R14   
              MOV     [RCX+jmp_buf.&R15], R15   
      
      
              SUB     RAX, RAX   
   @@1:   
   end;   
      
   procedure longjmp(const jmpb: jmp_buf; retval: UInt64);assembler;{$IFDEF   
   FPC} nostackframe; {$ENDIF}register;   
   asm   
   {     ->  RCX     jmpb   }   
   {         RDX     retval }   
   {     <-  RAX     Result }   
              XCHG    RDX, RCX   
              MOV     RAX,RCX   
              MOV     RCX, [RDX+jmp_buf.&RIP]   
              // Restore task state   
              MOV     RBX, [RDX+jmp_buf.&RBX]   
              MOV     RSI, [RDX+jmp_buf.&RSI]   
              MOV     RDI, [RDX+jmp_buf.&RDI]   
              MOV     RSP, [RDX+jmp_buf.&RSP]   
              MOV     RBP, [RDX+jmp_buf.&RBP]   
              MOV     R12, [RDX+jmp_buf.&R12]   
              MOV     R13, [RDX+jmp_buf.&R13]   
              MOV     R14, [RDX+jmp_buf.&R14]   
              MOV     R15, [RDX+jmp_buf.&R15]   
              MOV     [RSP], RCX  // Restore return address (RIP)   
      
              TEST    RAX, RAX    // Ensure retval is <> 0   
              JNZ     @@1   
              MOV     RAX, 1   
   @@1:   
   end;   
      
   end.   
      
   ================   
      
   And here is my example of a generator with my longjmp() and setjmp():   
      
      
   { In computer science, a generator is a routine that can be used to   
   control the iteration behaviour of a loop. All generators are also   
   iterators. A generator is very similar to a function that returns an   
   array, in that a generator has parameters, can be called, and generates   
   a sequence of values. However, instead of building an array containing   
   all the values and returning them all at once, a generator yields the   
   values one at a time, which requires less memory and allows the caller   
   to get started processing the first few values immediately. In short, a   
   generator looks like a function but behaves like an iterator. }   
      
   program test_generator;   
      
   {$APPTYPE CONSOLE}   
      
   uses   
       JmpLib64;   
      
   type PtrInt = ^Integer;   
      
   var   
      childtask,maintask: jmp_buf;   
      myarr1: array of integer;   
      i,a:integer;   
      Ptr1:PtrInt;   
      
   function generator(var myarr:array of integer):integer;   
      
   var i1:integer;   
        val:integer;   
        ptr:PtrInt;   
   begin   
      
      
   i1:=0;   
      
   val:= setjmp(childtask);   
      
   i1:=val-1;   
      
   if val=0 then   
       begin   
        new(ptr);   
        ptr^:=myarr1[i1];   
        longjmp(maintask,uint64(ptr));   
       end;   
      
   if val=10   
       then   
        begin   
   	 writeln('Exiting child..');   
   	 exit;   
   	end;   
      
     inc(i1);   
     new(ptr);   
     ptr^:=myarr1[i1];   
     longjmp(maintask,uint64(ptr));   
   end;   
      
   begin   
      
   setlength(myarr1,10);   
      
   for i:=0 to 9   
   do myarr1[i]:=i;   
      
   uint64(ptr1):=setjmp(maintask);   
      
   if ptr1=nil then generator(myarr1);   
      
   a:=ptr1^;   
   dispose(ptr1);   
      
   if (a<=length(myarr1))   
      then   
        begin   
          if a=length(myarr1)   
   	  then longjmp(childtask,a+1)   
   	  else   
   	    begin   
                  writeln('Value retuned by generator is: ',a);   
   	      longjmp(childtask,a+1);   
             end;   
   	end;   
      
   setlength(myarr1,0);   
      
   end.   
      
   ====   
      
      
   Thank you,   
   Amine Moulay Ramdane.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca