Πέμπτη 16 Ιουλίου 2026

Revision 6 Version 15 - Added: Assembler 64

' x86.cls as  32 Bit X86 Assembler
' from Arne Elster 2007 / 2008
' I add hash table for find labels for now
' this is the first work


Assembler =getobject("","m2000.x86")


MachineCode= lambda Assembler (assembly)-> {
if Assembler=>assemble(assembly, true) then
' get the output size
OutPutSize=Assembler=>OutputSize
buffer code mc as byte*OutputSize
' feed the base address to Assembler
Assembler=>BaseAddress=mc(0)
if Assembler=>assemble(assembly) then
' get a copy of final machine code
mc=>FillDataFromMem Assembler=>GetOutPtr
=mc
exit
end if
end if
error Assembler=>LastErrorMessage
}
Example=MachineCode({
ASM_TEST_RAWDATA:
mov eax, [Data]
ret 16
Data:
dd 123454321
ASM_TEST_BUBBLESORT: ; this is another program
pushad
mov esi, [ebp+16] ; Arraylength
outer_loop:
mov ebx, [ebp+12] ; ArrPtr
mov edx, [ebp+16] ; Arraylength
xor edi, edi
inner_loop:
mov eax, [ebx+0] ; arr(j)
mov ecx, [ebx+4] ; arr(j+1)
cmp eax, ecx
jle byte next_loop ; swap if eax > ecx
mov [ebx+0], ecx ; swap arr(j), arr(j+1)
mov [ebx+4], eax
mov edi, 1 ; swapped
next_loop:
add ebx, 4
dec edx
jnz byte inner_loop ; i > 0 => still in inner
test edi, edi ; swapped?
jz  byte return ; no => sorted
dec esi
jnz byte outer_loop
return:
popad
ret &H10
ASM_TEST_CPUID:
pushad
mov edi, [ebp+12]
xor eax, eax
cpuid
mov [edi+0], ebx
mov [edi+4], edx
mov [edi+8], ecx
popad
ret 16
ASM_TEST_FDIV:
mov   eax, [ebp+20] ; Ptr to output float
fild  dword [ebp+12] ; st0 = numerator
fild  dword [ebp+16] ; st0 = divisor, st1 = numerator
fdivp ; st1 = st1 / st0, pop st0
fstp  float [eax] ; pop st0 to output float
ret    16
})
ASM_TEST_RAWDATA=assembler=>labeloffset("ASM_TEST_RAWDATA")
ALTERDATA=assembler=>labeloffset("data")
ASM_TEST_BUBBLESORT=assembler=>labeloffset("ASM_TEST_BUBBLESORT")
ASM_TEST_CPUID=assembler=>labeloffset("ASM_TEST_CPUID")
ASM_TEST_FDIV=assembler=>labeloffset("ASM_TEST_FDIV")
' a1: Numerator
' a2: Divisor
' a3: Ptr to result (float = single)


' **NEW** call using Code! used for ExecuteReadWrite
' call using Code used for ExecuteRead (no write bytes to buffer Example)
' **NEW** use ; to bypass error from eax<>0 - and use EAX to read the value
Execute Code! Example, ASM_TEST_RAWDATA;
Print Eax
Return Example, ALTERDATA:=uint(-11112222) as long '(unsigned)
Execute Code! Example, ASM_TEST_RAWDATA;
' eax has value of eax from last execut code when we use the ; symbol
' eax is signed value
Print EAX=-11112222


buffer Bytes12 as byte*12
'**NEW** we can pass max 4 byvalue long values.
Execute Code! Example, ASM_TEST_CPUID, Bytes12(0);
HEX "CPUID:";chr$(Bytes12[0,12])
long lngDividend=2, lngDivisor=5
single sngQuotient
' here we pass by reference sngQuotient passing by value the Variable Pointer
Execute Code! Example, ASM_TEST_FDIV,lngDividend, lngDivisor, VarPtr(sngQuotient);
Print sngQuotient=0.4~
N=100 ' try 1000
buffer MyData as Long*n
for i=0 to N-1
MyData[i]=Uint(random(1, 100000)-49999)
print Sint(MyData[i]),
next
print
Execute Code! Example, ASM_TEST_BUBBLESORT, MyData(0), N-1;
for i=0 to N-1
print sint(MyData[i]),
next
print


Τετάρτη 15 Ιουλίου 2026

Subtractive Generator

 from https://rosettacode.org/wiki/Subtractive_generator#M2000_Interpreter

Class Subtractive_generator {
private:
  long mod10=10^9, si=0, sj=0
  dim state(55) as long
  module subrand_seed (p1 as long) {
   long i, j=21, p2=1, d
   .state(0)=p1 mod .mod10
   for i=1 to 54
     if j>=55 then j-=55
     .state(j)=p2
     p2=p1-p2
     if p2<0 then p2+=.mod10
     p1=.state(j)
     j+=21
   next
   .si<=0
   .sj<=24
  }
public:
  property counter {
    value
  }=55&
  module advance (n) {
    for i=1 to n:d=.subrand():next  
  }
  function subrand {
    long x
    if .si=.sj then .subrand_seed 0
    .si--:if .si<0 then .si<=54
    .sj--:if .sj<0 then .sj<=54
    x=.state(.si)-.state(.sj)
    if x<0 then x+=.mod10
    .state(.si)=x
    =x
    .[counter]++
  }
class:
    module Subtractive_generator {
      .subrand_seed
    }
}
sg=Subtractive_generator(292929&)
sg.advance 220-55
sg1=sg ' copy of sg
for i=1 to 10
  print str$(sg.counter, "\r\[000\] = ")+sg.subrand()
next
print "== copy ==" ' print same numbers as before
for i=1 to 10
  print str$(sg1.counter, "\r\[000\] = ")+sg1.subrand()
next


r[220] = 467478574
r[221] = 512932792
r[222] = 539453717
r[223] = 20349702
r[224] = 615542081
r[225] = 378707948
r[226] = 933204586
r[227] = 824858649
r[228] = 506003769
r[229] = 380969305
== copy ==
r[220] = 467478574
r[221] = 512932792
r[222] = 539453717
r[223] = 20349702
r[224] = 615542081
r[225] = 378707948
r[226] = 933204586
r[227] = 824858649
r[228] = 506003769
r[229] = 380969305


Πέμπτη 9 Ιουλίου 2026

Έκδοση 15 Αναθεώρηση 2 - Χειρισμός Bits έως 64bit

 Νέες συναρτήσεις για χειρισμό bits σε 64bit εύρους τιμές. Μπορούμε να αλλάζουμε μπιτ, να ελέγχουμε καθώς και όλες τις άλλες δυνατότητες που έχουν και οι επεξεργαστές (CPU), όπως ολίσθηση και περιστροφή.

b=ΔΥΑΔ64.ΑΠΟ(0xFFFF_FFFF_FFFF_FFFF,0xAAAA_AAAA_AAAA_AAAA)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΚΑΙ(b, 0xFFFF_0000_0000_FFFF)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.Η(b, 0x1234_5678_0000)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΠΡΟΣΘΕΣΗ(b, 0X8000_0000_0000_0001)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΠΡΟΣΘΕΣΗ(b, 0X8000_0000_0000_0001)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΟΛΙΣΘΗΣΗ(b, 8)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΟΛΙΣΘΗΣΗ(b, -32)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΠΕΡΙΣΤΡΟΦΗ(b, -16)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΟΧΙ(b)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΚΑΙ(b,0Xffff_ffff_ffff)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΑΝΤΙΣΤΡΟΦΟ(b)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΑΝΤΙΣΤΡΟΦΟ(0x7FF_FFFF_FFFF_FFFF)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΑΝΤΙΣΤΡΟΦΟ(b)
ΔΕΚΑΕΞ b
b=ΔΥΟΜΙΣΑ64(0XAAAA_1234, 0xBBBB_5555)
ΔΕΚΑΕΞ b
b=ΔΥΟΜΙΣΑ(0XAAAA, 0x5555)
ΔΕΚΑΕΞ b
' ΔΥΑΔΙΚΟ.ΠΡΟΣΘΕΣΗ(a,b,c, ....)
b1=ΔΥΑΔΙΚΟ.ΠΡΟΣΘΕΣΗ(0X8000_0001, 0xFFFF_1234, 1)
ΔΕΚΑΕΞ b1, ΠΑΝΩΜΙΣΟ(b1), ΚΑΤΩΜΙΣΟ(b1)
b=ΔΥΑΔ64.ΠΡΟΣΘΕΣΗ(b, 0xFFFF_1234_0000_0000)
ΔΕΚΑΕΞ b, ΠΑΝΩΜΙΣΟ64(b), ΚΑΤΩΜΙΣΟ64(b)
ΔΕΚΑΕΞ ΔΥΟΜΙΣΑ64(ΚΑΤΩΜΙΣΟ64(b), ΠΑΝΩΜΙΣΟ64(b))
' ΔΥΑΔΙΚΟ.ΑΦΑΙΡΕΣΗ(a,b,c, ....)
b=ΔΥΑΔΙΚΟ.ΑΦΑΙΡΕΣΗ(0XFFFF_0001, 0XFFFF_0005, 1)
ΔΕΚΑΕΞ b, ΠΑΝΩΜΙΣΟ(b), ΚΑΤΩΜΙΣΟ(b)
b=ΔΥΑΔ64.ΑΦΑΙΡΕΣΗ(0X0000_FFFF_FFFF_0001, 0XFFFF_FFFF_FFFF_0005, 1)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΒΑΛΕ(b,62)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΒΓΑΛΕ(b,47)
ΔΕΚΑΕΞ b
ΤΥΠΩΣΕ ΔΥΑΔ64.ΕΧΕΙ(b, 29, 27)=true
b=ΔΥΑΔ64.ΒΓΑΛΕ(b,29, 15)
ΔΕΚΑΕΞ b
B=ΔΥΑΔ64.ΒΑΛΕ(0,60,58,4,1) ' make a 64bit setting 4 bits
ΔΕΚΑΕΞ b
ΤΥΠΩΣΕ ΔΥΑΔ64.ΕΧΕΙ(b, 57)=false
B=ΔΥΑΔ64.ΒΑΛΕ(b,57)
ΔΕΚΑΕΞ b
ΤΥΠΩΣΕ ΔΥΑΔ64.ΕΧΕΙ(b, 57)=true
b2=ΔΥΑΔΙΚΟ.ΒΑΛΕ(0,9,8,0)
ΔΕΚΑΕΞ b2
ΤΥΠΩΣΕ b2=0x301 ' bit 9,8,0
ΔΕΚΑΕΞ ΤΙΜΗ(2^9+2^8+2^0->ΛΟΓΙΣΤΙΚΟΣ), b2
b2=ΔΥΑΔΙΚΟ.ΒΓΑΛΕ(b2,12, 8)
ΔΕΚΑΕΞ b2,
ΤΥΠΩΣΕ b2=0x201
ΤΥΠΩΣΕ ΔΥΑΔ(-1%)=0ΧFFFF
ΤΥΠΩΣΕ ΔΥΑΔ(-1)=0ΧFFFF_FFFF
ΤΥΠΩΣΕ ΔΥΑΔ64(-1)=0ΧFFFF_FFFF_FFFF_FFFF
ΤΥΠΩΣΕ ΔΥΑΔΙΚΟ.ΑΚΕΡΑΙΟ64(-1)=0ΧFFFF_FFFF_FFFF_FFFF
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΔΥΑΔΙΚΟ.ΑΚΕΡΑΙΟ64(-1))="Decimal"
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF, 2)=0XFFFF%
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF, 4))="Currency"
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF, 4)=0XFFFF_FFFF&
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF))="Long Long"
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF)=0XFFFF_FFFF_FFFF_FFFF&&
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFAA, 8)=0ΧFFFF_FFAA&&
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFAA, 8))="Long Long"

Και στα αγγλικά:

b=BIT64.XOR(0xFFFF_FFFF_FFFF_FFFF,0xAAAA_AAAA_AAAA_AAAA)
hex b
b=BIT64.AND(b, 0xFFFF_0000_0000_FFFF)
hex b
b=BIT64.OR(b, 0x1234_5678_0000)
hex b
b=BIT64.ADD(b, 0X8000_0000_0000_0001)
hex b
b=BIT64.ADD(b, 0X8000_0000_0000_0001)
hex b
b=BIT64.SHIFT(b, 8)
hex b
b=BIT64.SHIFT(b, -32)
hex b
b=BIT64.ROTATE(b, -16)
hex b
b=BIT64.NOT(b)
hex b
b=BIT64.AND(b,0Xffff_ffff_ffff)
hex b
b=BIT64.NEG(b)
hex b
b=BIT64.NEG(0x7FF_FFFF_FFFF_FFFF)
hex b
b=BIT64.NEG(b)
hex b
b=HILOWLONG(0XAAAA_1234, 0xBBBB_5555)
hex b
b=HILOWWORD(0XAAAA, 0x5555)
hex b
' BINARY.ADD(a,b,c, ....)
b1=BINARY.ADD(0X8000_0001, 0xFFFF_1234, 1)
hex b1, HIWORD(b1), LOWORD(b1)


b=BIT64.ADD(b, 0xFFFF_1234_0000_0000)
hex b, HILONG(b), LOLONG(b)
hex HILOWLONG(LOLONG(b), HILONG(b))
' BINARY.SUB(a,b,c, ....)
b=BINARY.SUB(0XFFFF_0001, 0XFFFF_0005, 1)
hex b, HIWORD(b), LOWORD(b)
b=BIT64.SUB(0X0000_FFFF_FFFF_0001, 0XFFFF_FFFF_FFFF_0005, 1)
hex b
b=BIT64.SET(b,62)
hex b
b=BIT64.RESET(b,47)
hex b
print BIT64.TEST(b, 29, 27)=true
b=BIT64.RESET(b,29, 15)
hex b
B=BIT64.SET(0,60,58,4,1) ' make a 64bit setting 4 bits
hex b
print BIT64.TEST(b, 57)=false
B=BIT64.SET(b,57)
hex b
print BIT64.TEST(b, 57)=true
b2=BINARY.SET(0,9,8,0)
hex b2
print b2=0x301 ' bit 9,8,0
hex val(2^9+2^8+2^0->currency), b2
b2=BINARY.RESET(b2,12, 8)
hex b2,
print b2=0x201
print uint(-1%)=0ΧFFFF
print uint(-1)=0ΧFFFF_FFFF
print uint64(-1)=0ΧFFFF_FFFF_FFFF_FFFF
print type(uint64(-1))="Decimal"
print sint(0ΧFFFF_FFFF_FFFF_FFFF, 2)=0XFFFF%
print type(sint(0ΧFFFF_FFFF, 4))="Currency"
print sint(0ΧFFFF_FFFF_FFFF_FFFF, 4)=0XFFFF_FFFF&
print type(sint(0ΧFFFF_FFFF_FFFF_FFFF))="Long Long"
print sint(0ΧFFFF_FFFF_FFFF_FFFF)=0XFFFF_FFFF_FFFF_FFFF&&
print sint(0ΧFFFF_FFAA, 8)=0ΧFFFF_FFAA&&
print type(sint(0ΧFFFF_FFAA, 8))="Long Long"



Τετάρτη 8 Ιουλίου 2026

Shift 64bit (using 32bit shift)

This is a module to demostrate the bit shift for 64bit using 32bit shifts (and rotate). The HiLow structure define a union of a long long (64bit) unsigned integer with two long (32bit) unsigned integers. For 32 bit unsinged integers we use currency variables (because they can hold all the possible values), and this is the return type from binary.xxx() functions. For 64 bit unsigned integers we use decimal type. So a 0xFFFF_FFFF_FFFF_FFFF is a decimal type with the value of an unsigned integer 64bit equal to 18446744073709551615 decimal. We can use 18446744073709551615@ to define decimal literal. The 0xFFFF_FFFF_FFFF_FFFF&& literal is a signed long long and has value -1. M2000 use & for signed long, so 0xFFFF_FFFF& is -1 long, and use % for signed integer 16bit, so 0xFFFF% is -1. Also there is the Byte which is always unsigned from 0 to 255. So we make a HiLow variable (a buffer type) z and that became a closure to final lambda function (buffers are reference type so we put the pointer to lambda). Using buffer we can pass the address using z(0) which 0 is the offset of first item (the z has one item now but we can make it with many more) to an external function (passing the address is same like passing by reference but not the reference of the reference, so the reference stay as is, the value can be change). M2000 functions can use "reference of reference" if we use &z from each side (from caller and callee should defined as byreference using &), so if we pass a reference type by reference you can change the reference not only the value. This isn't something to do here. We only use the union to get the value of low long or high long  of the 64 bit long long.


Module Shift64bit {
  bit.shift=lambda ->{
    structure HiLow {
      {ab as long long} 'union with 2 long
      a as long, b as long
    }
    HiLow z ' make a z and put as closure to lambda
    =lambda z (z|ab, b, only32bit as boolean=false)-> {
      if abs(b)>63 then
        z|ab=0
      else.if b<-31 then
        b+=32
        z|a=binary.shift(z|b, b)
        z|b=0
      else.if b<0 then
        mask=binary.shift(0xFFFFFFFF, 32+b)
        z|a=binary.and(binary.rotate(z|b, b), mask)+binary.shift(z|a, b)
        z|b=binary.shift(z|b, b)
      else.if b=0 then
      else.if b<31 then
        mask=binary.shift(0xFFFFFFFF, b-32)
        z|b=binary.shift(z|b, b)+binary.and(binary.rotate(z|a, b), mask)
        z|a=binary.shift(z|a, b)
      else
        b-=32
        z|b=binary.shift(z|a, b)
        z|a=0
      end if
      if only32bit then =z|a else =z|ab  
    }
  }()
  a=0x1234AAAA
  aa=a+0xFFFF_AAAA_0000_0000
  for n=-64 to 64 step 4
    if abs(n)>63 then
      b=0#
      c=0@
    else
      refresh 100
      if abs(n)>31 then
        b=0
      else
        b=binary.shift(a, n)
      end if
      c=bit.shift(aa, n)
    end if
    print "bit shift:";n
    
    hex a
    hex b
    hex aa
    hex c
    push key$: drop
  next
  refresh 25
}
Shift64bit

 

Long multiplication using variable base (from 2 to 36)

A long multiplication using a lambda function with closures two lists, so we do the multiplication and additions using "memory". Also carry addition performed using "memory" also (through precalculated lists). We have to produce the final lambda by passing the base for the numbers. All computations use only strings in final lambda.

function placecoma(a as string) {
  if len(a)<4 then =a :exit  
  k=StrRev$(a)
  a=""
  for i=4 to len(k) step 3
    a+=mid$(k,i-3, 3)+","
  next
  a+=mid$(k, i-3)
  a=strrev$(a)
  if left$(a,1)="," then =mid$(a,2) else =a
}
long_mul=lambda (s=10) ->{
  m=list
  ad=list
  s1=s-1
  symb="0123456789ABCDEFGHIJKLMNOPQRSTUVWXZ"
  for i=0 to s1:for j=0 to s1:
    c=i*j
    if c<s then
      m(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,c+1,1)
    else
      m(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,(c div s)+1,1)+mid(symb,(c mod s)+1,1)
    end if  
  next:next
  for i=0 to s1:for j=0 to s1:
    c=i+j
    if c<s then
      ad(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,c+1,1)
    else
      ad(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,(c div s)+1,1)+mid(symb,(c mod s)+1,1)
    end if
  next:next    
  =lambda m, ad (a as string, b as string) -> {    
    a=filter(a,",")
    b=filter(b,",")
    sign=1
    if left(a,1)="-" then sign=-1:insert 1,1 a=""
    if left(b,1)="-" then sign*=-1:insert 1,1 b=""
    ii=len(b)+1
    jj=len(a)+1
    zero=0
    acc="0"
    f=list:=0
    if a="0" then =a :exit
    for i=1 to len(b)
      bb=mid(b,ii-i,1)
      c="0"
      if not exist(f, bb) then
        dd=string$("0", len(a))
        for j=1 to len(a)
          d=m(mid(a,jj-j,1)+bb)
          if c<>"0" then
            if len(d)>1 then              
              d1=ad(right(d,1)+c)
              if len(d1)>1 then
                d2=ad(left(d,1)+left(d1,1))
                d=d2+d1
              else
                insert 2,1 d=d1
              end if
            else
              d=ad(d+c)
            end if
          end if
          c="0" :  if len(d)>1 then c=left(d,1):d=right(d,1)
          insert jj-j,1 dd=d
        next
        if c<>"0" then f(bb)=c+dd else f(bb)=dd
      end if
      if bb<>"0" then
        p1=len(f(bb))
        p=len(acc)-zero
        if p<1 then
          acc=string$("0",2-p)+acc
          p=len(acc)-zero
        end if
        c="0"
        for kk=p1 to 1
          d=""+ad(mid(acc, p,1)+mid(f(bb),kk,1))
          if c<>"0" then
            if len(d)>1 then              
              d1=ad(right(d,1)+c)
              if len(d1)>1 then
                d2=ad(left(d,1)+left(d1,1))
                d=d2+d1
              else
                insert 2,1 d=d1
              end if
            else
              d=""+ad(d+c)
            end if
          end if          
          c="0" : if len(d)>1 then c=left(d,1):d=right(d,1)
          insert p, 1 acc=d
          p-- : if p<1 and kk>1 then p=1:acc=c+acc:c="0"
        next
        if c<>"0" then
        if p<1 then acc=c+acc else insert p, 1 acc=c
        end if
      end if
      zero+=1
    next
    if sign<0 then
      ="-"+acc
    else
      =acc
    end if
  }
}
long_mul10=long_mul(10)
a="18,446,744,073,709,551,616"
print placecoma(long_mul10(a, a))="340,282,366,920,938,463,463,374,607,431,768,211,456"
print long_mul10("-832764873673674323484", "234242938742937483278432798279428")=""+(-832764873673674323484u*234242938742937483278432798279428u)
long_mul2=long_mul(2)
print long_mul2("1010101","11")="11111111"
long_mul16=long_mul(16)
print long_mul16("55","3")="FF", 0x55*0x3=0xFF


print long_mul16("55","2")="AA"
long_mul8=long_mul(8)
print long_mul8("7","2")="16"  ' 14 = 14