More of my philosophy about setjmp() and longjmp() and generators and c
From
World-News2100@21:1/5 to
All on Tue Nov 23 15:21:15 2021
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: fsxNet Usenet Gateway (21:1/5)