' 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
Execute Code! Example, ASM_TEST_BUBBLESORT, MyData(0), N-1;
for i=0 to N-1
print sint(MyData[i]),
next
Πληροφορική - Προγραμματισμός
Επίσημος τόπος για τη γλώσσα προγραμματισμού Μ2000 Έκδοση 15 Αναθ. 4
Πέμπτη 16 Ιουλίου 2026
Revision 6 Version 15 - Added: Assembler 64
Τετάρτη 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.
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