pass is trivial.
poke is working.
Now to do bitwise and…
pass is trivial.
poke is working.
Now to do bitwise and…
Hello world the easy way…
print('Hello world!')
and the hard way…
poke(-12288, 72)
poke(-12288, 101)
poke(-12288, 108)
poke(-12288, 108)
poke(-12288, 111)
poke(-12288, 32)
poke(-12288, 87)
poke(-12288, 111)
poke(-12288, 114)
poke(-12288, 108)
poke(-12288, 100)
poke(-12288, 33)
poke(-12288, 13)
poke(-12288, 10)
How about …
for c in "Hello World!":
poke(-12288, ord(c))
Unfortunately, iterators are still far off. I do not fully understand how to create one yet.
That is why I have a while loop but not a for loop.
Bitwise and is in there and this code
while peek(-12287) & 8 == 0:
pass
poke(-12288, peek(-12288))
works as expected.
How about
i = 65
while i < 91:
poke(-12288, i)
i = i + 1
The generated code:
00098 ; 00001 i = 65
00099
020E AE 287E [4] 00100 ldx _i
0211 AD 287F [4] 00101 lda _i+1
0214 20 04A5 [6] 00102 jsr DeRef
00103
0217 A2 77 [2] 00104 ldx #I_00065&$FF
0219 A9 28 [2] 00105 lda #I_00065>>8
021B 8E 287E [4] 00106 stx _i
021E 8D 287F [4] 00107 sta _i+1
00108 ; 00002 while i < 91:
0221 00109 L00000
0221 A2 79 [2] 00110 ldx #I_00091&$FF
0223 A9 28 [2] 00111 lda #I_00091>>8
0225 86 1A [3] 00112 stx Ptr1
0227 85 1B [3] 00113 sta Ptr1+1
0229 A2 7E [2] 00114 ldx #_i&$FF
022B A9 28 [2] 00115 lda #_i>>8
022D 20 0C40 [6] 00116 jsr GetObject
0230 86 18 [3] 00117 stx Ptr0
0232 85 19 [3] 00118 sta Ptr0+1
0234 20 1A86 [6] 00119 jsr object.__lt__
0237 20 0646 [6] 00120 jsr object.__bool__
023A D0 03 (023F) [2/3] 00121 bne L00001
023C 4C 0292 [3] 00122 jmp L00002
023F 00123 L00001
00124 ; 00003 poke(-12288, i)
023F A9 02 [2] 00125 lda #2
0241 A2 00 [2] 00126 ldx #0
0243 20 0C58 [6] 00127 jsr AllocPargsAndKargs
0246 A0 05 [2] 00128 ldy #5
0248 A2 7E [2] 00129 ldx #_i&$FF
024A A9 28 [2] 00130 lda #_i>>8
024C 20 0C40 [6] 00131 jsr GetObject
024F 20 0CBE [6] 00132 jsr StoreParg
0252 A2 7B [2] 00133 ldx #I__12288&$FF
0254 A9 28 [2] 00134 lda #I__12288>>8
0256 20 0CBE [6] 00135 jsr StoreParg
0259 A2 83 [2] 00136 ldx #_poke&$FF
025B A9 28 [2] 00137 lda #_poke>>8
025D 20 0C40 [6] 00138 jsr GetObject
0260 20 0D03 [6] 00139 jsr object.__call__
0263 20 0CE0 [6] 00140 jsr FreePargsAndKargs
00141 ; 00004 i = i + 1
0266 A2 75 [2] 00142 ldx #I_00001&$FF
0268 A9 28 [2] 00143 lda #I_00001>>8
026A 86 1A [3] 00144 stx Ptr1
026C 85 1B [3] 00145 sta Ptr1+1
026E A2 7E [2] 00146 ldx #_i&$FF
0270 A9 28 [2] 00147 lda #_i>>8
0272 20 0C40 [6] 00148 jsr GetObject
0275 86 18 [3] 00149 stx Ptr0
0277 85 19 [3] 00150 sta Ptr0+1
0279 20 1049 [6] 00151 jsr object.__add__
00152
027C AE 287E [4] 00153 ldx _i
027F AD 287F [4] 00154 lda _i+1
0282 20 04A5 [6] 00155 jsr DeRef
00156
0285 A6 16 [3] 00157 ldx PtrA
0287 A5 17 [3] 00158 lda PtrA+1
0289 8E 287E [4] 00159 stx _i
028C 8D 287F [4] 00160 sta _i+1
028F 4C 0221 [3] 00161 jmp L00000
0292 00162 L00002
00163
0292 60 [6] 00164 rts
Great! … thanks for that
Was the invalid opcode error a way to exit? You could poke something to exit, I suppose
Yes, I am currently emulating just the processor, RAM and a serial port. There is no operating system to exit to. So the invalid instruction passes control back to the debugger.
I’ve been working on assembly/disassembly and learning several machine languages … currently, delving more into x86 and also tms34010 (one of the first graphics processors from TI) and m68k assembly. I’m still wanting to convert them into an intermediate language and back into source or other assembly languages. The latter two are part of the Robotic Arm Controller.
I know 68K…
Excellent … I may have a few questions for you from time to time … but it is not just about the assembly but the system. I am having to figure out where the memory mapped I/O is and all of that. It is interesting because there are many CPUs of different architectures using the same memory at the same time, communicating between each other using interrupts and memory.
Have you ever used Radare2? It is a great Disassembler. It also graphs like IDA Pro but it is free.
https://rada.re/r/
It is all text based and has I high learning curve because of all the commands but it can emulate processors and disassemble/assembly on the fly. It has some issues with some of the non-popular architectures but I’m also working on improving them.
Architectures:
6502, 8051, CRIS, H8/300, LH5801, T8200, arc, arm, avr, bf, blackfin, xap, dalvik, dcpu16, gameboy, i386, i4004, i8080, m68k, malbolge, mips, msil, msp430, nios II, powerpc, rar, sh, snes, sparc, tms320 (c54x c55x c55+), V810, x86-64, zimg, risc-v.
File Formats:
bios, CGC, dex, elf, elf64, filesystem, java, fatmach0, mach0, mach0-64, MZ, PE, PE+, TE, COFF, plan9, dyldcache, Commodore VICE emulator, Game Boy (Advance), Nintendo DS ROMs and Nintendo 3DS FIRMs.
Operating Systems:
Android, GNU/Linux, [Net|Free|Open]BSD, iOS, OSX, QNX, w32, w64, Solaris, Haiku, FirefoxOS
Bindings:
Vala/Genie, Python (2, 3), NodeJS, Lua, Go, Perl, Guile, php5, newlisp, Ruby, Java, OCaml, …
Never heard of it.
_
It uses internally
Unicorn Engine for emulation
Capstone for disassembly
What I like about it is it will analyse the code and find functions/symbols … break it apart into sections
It looks like they forked them and added a bunch on to them to support other arches
The compiler with native big number support just came to life.
I can now compile and run Dave’s program:
n = 30000 + 40000
print(n)
n = 30000 - 40000
print(n)
n = 90000 + 40000
print(n)
n = 1000000 + 40000
print(n)
n = 500000 + 40000
print(n)
What is missing is the constant folding optimization - all of these calculations are currently being done at run-time. It may be awhile before I get constant folding back to the way I had it.
While working on this, I managed to sneak in:
peek function
poke function
bitwise and & operator
bitwise exclusive or ^ operator
bitwise or | operator
I still have several weeks until the retrocomputing meeting when I plan to make a release. What kind of things should I try to implement between now and then?
I doubt I can let you define your own functions in that time.
I can implement input, but without string indexing and slicing, there is not much you can do with it. I suppose I can implement the int function to convert a string to a number…
Other ideas?
A little bit of foreshadowing of what is to come…
00101 ; 00001 b = ''
00102
020E AE 2DD1 [4] 00103 ldx _b
0211 AD 2DD2 [4] 00104 lda _b+1
0214 20 04E8 [6] 00105 jsr DeRef
00106
0217 A2 CE [2] 00107 ldx #S_00000&$FF
0219 A9 2D [2] 00108 lda #S_00000>>8
021B 8E 2DD1 [4] 00109 stx _b
021E 8D 2DD2 [4] 00110 sta _b+1
00111 ; 00002 while b != 'n':
0221 00112 L00000
0221 A2 BE [2] 00113 ldx #S_00001&$FF
0223 A9 2D [2] 00114 lda #S_00001>>8
0225 86 1A [3] 00115 stx Ptr1
0227 85 1B [3] 00116 sta Ptr1+1
0229 A2 D1 [2] 00117 ldx #_b&$FF
022B A9 2D [2] 00118 lda #_b>>8
022D 20 0C89 [6] 00119 jsr GetObject
0230 86 18 [3] 00120 stx Ptr0
0232 85 19 [3] 00121 sta Ptr0+1
0234 20 1D6A [6] 00122 jsr object.__ne__
0237 86 26 [3] 00123 stx Tmp0
0239 85 27 [3] 00124 sta Tmp0+1
023B 20 0689 [6] 00125 jsr object.__bool__
023E 8A [2] 00126 txa
023F 48 [3] 00127 pha
0240 A6 26 [3] 00128 ldx Tmp0
0242 A5 27 [3] 00129 lda Tmp0+1
0244 20 04E8 [6] 00130 jsr DeRef
0247 68 [4] 00131 pla
0248 C9 B8 [2] 00132 cmp #False&$FF
024A D0 03 (024F) [2/3] 00133 bne L00001
024C 4C 02CD [3] 00134 jmp L00002
024F 00135 L00001
00136 ; 00003 print(randint(1, 10))
024F A9 02 [2] 00137 lda #2
0251 A2 00 [2] 00138 ldx #0
0253 20 0CA1 [6] 00139 jsr AllocPargsAndKargs
0256 A0 05 [2] 00140 ldy #5
0258 A2 CC [2] 00141 ldx #I_10&$FF
025A A9 2D [2] 00142 lda #I_10>>8
025C 20 0D07 [6] 00143 jsr StoreParg
025F A2 BC [2] 00144 ldx #I_1&$FF
0261 A9 2D [2] 00145 lda #I_1>>8
0263 20 0D07 [6] 00146 jsr StoreParg
0266 A2 DF [2] 00147 ldx #_randint&$FF
0268 A9 2D [2] 00148 lda #_randint>>8
026A 20 0C89 [6] 00149 jsr GetObject
026D 20 0D4C [6] 00150 jsr object.__call__
0270 20 0D29 [6] 00151 jsr FreePargsAndKargs
0273 A5 17 [3] 00152 lda PtrA+1
0275 48 [3] 00153 pha
0276 A5 16 [3] 00154 lda PtrA
0278 48 [3] 00155 pha
0279 A9 01 [2] 00156 lda #1
027B A2 00 [2] 00157 ldx #0
027D 20 0CA1 [6] 00158 jsr AllocPargsAndKargs
0280 A0 03 [2] 00159 ldy #3
0282 68 [4] 00160 pla
0283 AA [2] 00161 tax
0284 68 [4] 00162 pla
0285 20 0D07 [6] 00163 jsr StoreParg
0288 A2 D6 [2] 00164 ldx #_print&$FF
028A A9 2D [2] 00165 lda #_print>>8
028C 20 0C89 [6] 00166 jsr GetObject
028F 20 0D4C [6] 00167 jsr object.__call__
0292 A0 02 [2] 00168 ldy #2
0294 20 0D17 [6] 00169 jsr DerefParg
0297 20 0D29 [6] 00170 jsr FreePargsAndKargs
00171 ; 00004 b = input('again? ')
029A A9 01 [2] 00172 lda #1
029C A2 00 [2] 00173 ldx #0
029E 20 0CA1 [6] 00174 jsr AllocPargsAndKargs
02A1 A0 03 [2] 00175 ldy #3
02A3 A2 C2 [2] 00176 ldx #S_00002&$FF
02A5 A9 2D [2] 00177 lda #S_00002>>8
02A7 20 0D07 [6] 00178 jsr StoreParg
02AA A2 EA [2] 00179 ldx #_input&$FF
02AC A9 2D [2] 00180 lda #_input>>8
02AE 20 0C89 [6] 00181 jsr GetObject
02B1 20 0D4C [6] 00182 jsr object.__call__
02B4 20 0D29 [6] 00183 jsr FreePargsAndKargs
00184
02B7 AE 2DD1 [4] 00185 ldx _b
02BA AD 2DD2 [4] 00186 lda _b+1
02BD 20 04E8 [6] 00187 jsr DeRef
00188
02C0 A6 16 [3] 00189 ldx PtrA
02C2 A5 17 [3] 00190 lda PtrA+1
02C4 8E 2DD1 [4] 00191 stx _b
02C7 8D 2DD2 [4] 00192 sta _b+1
02CA 4C 0221 [3] 00193 jmp L00000
02CD 00194 L00002
Revisited while and implemented else, break and continue.
Now this code
repeat = 0
while repeat < 2:
counter = 0
while counter < 5:
if counter == 2:
counter = counter + 1
continue # Skip 2
print(counter, ': Inside loop')
if repeat == 0:
if counter == 3:
break # Quit after 3 the first time
counter = counter + 1
else:
print('Inside else')
repeat = repeat + 1
gives this output
0 : Inside loop
1 : Inside loop
3 : Inside loop
0 : Inside loop
1 : Inside loop
3 : Inside loop
4 : Inside loop
Inside else
This is the document to go with my first public release of the compiler.
Please read and comment. Thanks.
PY65.PDF (65.9 KB)
There are a few additional features which may sneak in.
Edit: Dang, Missed it by >< that much. The size was almost 65.02 KB…