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