< December 2021 >
MonTueWedThuFriSatSun
29300102030405
06070809101112
13141516171819
20212223242526
27282930310102

Wednesday, 22 December 2021

05:00 PM

Neal Moore Completes Epic Journey Across the US in a Canoe [The Adventure Blog] 05:00 PM, Wednesday, 22 December 2021 04:00 AM, Thursday, 06 January 2022

From February 2020 until December 2021, adventurer Neal Moore is going the distance in a continuous storytelling expedition from Astoria, Oregon on the Pacif...

02:37 AM

Writing a SNES assembler compiler/disassembler - Day 3 [blogs.perl.org] 02:37 AM, Wednesday, 22 December 2021 09:40 PM, Tuesday, 21 December 2021

Assembling the Assembler

Grammar fix

When starting implementing the compiler part of this. I noticed that the grammar does not actually really work, especially if you introduce new lines. If I parse a file with 3 instructions, we catch the \n sometime and the asm-comment token is too greedy.

Let's change the ws rule to only capture horizontal blank (space and tab) and introduce an eol token, this makes the grammar more clear on what we are working on also.

token TOP { <.eol>* <thing>+ $ } token thing { || <asm-comment> <.eol> || <one-instruction> <.eol> || <instruction-line> <.ws> <.asm-comment>? <.eol> } token instruction-line { <instruction> (<.ws> ':' <.ws> <instruction>)+ } token one-instruction { <instruction> <.ws> <.asm-comment>? } token asm-comment { ';' <-[\n]>* } token ws { <!ww> \h* } token eol { \n[\h*\n]* } }
 

Capturing thing

With grammar in Raku, you associate an Action class to your grammar to transform the AST or just do what you want when you encounter a token.

It's really a simple mechanism, you define a class with methods that have the same name as your token and that's all. You don't need to have a method for every token and for our purpose we mainly only need to catch the <instruction> tokens. The catch for our code, since we use a proto token for <instruction> and multiple generated token like token instruction:sym<TRB-DIRECT-PAGE> defining an instruction method does not work. The method must match the name of the generated token, but we don't need to generate a method for every token since Raku offers a pseudo method called FALLBACK that catch-all method calls on our class that are not defined.

The method look like this :

method FALLBACK ($name, $match) { if $name ~~ /^instruction':sym<'(.+?)['-'(.*?)]**0..1'>'/ { my $int = CompilableInstruction.new; $int.name = $/[0].Str; $int.text = $match.Str; my $parsed = $match.target.substr(0, $match .pos).trim-trailing; with $/[1] { $int.addressing = ASM65816::AddressingMode::<<$/[1]>>; $int.lenght = %map-instructions{$int.name}{$int.addressing}.lenght; $int.operand = $int.lenght == 1 ?? -1 !! $!last-value; } else { $int.addressing = IMPLIED; $int.operand = -1; $int.lenght = 1; } $int.op-code = %map-instructions{$int.name}{$int.addressing}.op-code; @!see-instructions.push($int); } }
 

The instructions are stored in a CompilableInstruction class to make them more interesting to use.

I removed my generated array of instructions and replaced it with a %map-instructions that map my instruction information according to their 'name' and their addressing mode. This will be very useful to report what addressing mode an instruction support in case of error.

BIT => { DIRECT-PAGE => Instruction.new(:inst("BIT"), :addressing(DIRECT-PAGE), :description("Test Bits"), :op-code(36), :alias(""), :lenght(2)), ABSOLUTE => Instruction.new(:inst("BIT"), :addressing(ABSOLUTE), :description("Test Bits"), :op-code(44), :alias(""), :lenght(3)), DP-INDEXED-X => Instruction.new(:inst("BIT"), :addressing(DP-INDEXED-X), :description("Test Bits"), :op-code(52), :alias(""), :lenght(2)), ABSOLUTE-INDEXED-X => Instruction.new(:inst("BIT"), :addressing(ABSOLUTE-INDEXED-X), :description("Test Bits"), :op-code(60), :alias(""), :lenght(3)), IMMEDIATE => Instruction.new(:inst("BIT"), :addressing(IMMEDIATE), :description("Test Bits"), :op-code(137), :alias(""), :lenght(2)), },
 

Today I learn - Be mindful of $/

You can see that I named the Match argument of FALLBACK to $match. In most grammar examples it will be named $/ like the implicit variable affect when you use a regex. But it's a small trap. You can see that I use a regex to match and capture part of the method name so $/ get reaffected and you get a runtime error that tell you that you affected a read-only variable (method/sub arguments are read only by default)

Getting the value

We also need to capture the operand of the instruction, we could get it at grammar level and add the value to the ast when parsing a byte, word or long, but you need to propagate the change the ast for each parent token up to the instruction. There is a more simple solution, you can note that I assign the operand with an attribute called last-value it's because I simply catch each byte, word, long token in the action class and affect them to this attribute.

method long($/) { self.word($/); $!value-type = ValueType::long; } method byte ($/) { self.word($/); $!value-type = ValueType::byte; } method word ($cap) { $!last-value = $cap.Str.starts-with('$') ?? $cap.Str.substr(1).parse-base(16) !! $cap.Str.parse-base(10); $!value-type = ValueType::word; }
 

I actually don't use the ValueType for now, but maybe that will be useful later.

Showing the result

Next step is to write a Str/gist method on the CompilableInstruction class to have a nice output so we can display the @.instructions from the action class. This array is built from the @!see-instructions when we encounter a <one-instruction> or <instruction-line> token. This is probably not needed now, but my previous grammar was causing some instruction to be seen twice on a bad match.

Let assemble one of my small test files.

lda 42 ; boring rtl ; I love comment rtl ; meh
 

I also wrote a sub to display the value according to the addressing mode so the Str method can 'rebuild' the text.

The program output look like this, so far so good

A5:2A LDA $2A 6B: RTL 6B: RTL
 

To generate the bytecode I just add an assemble method on my instruction class that returns a buf8 containing the bytes from the instruction information. It's actually pretty straightforward since we just need to take the op-code and append the encoded operand in LittleEndian.

# There is no write-uint24 method :) method !encode-long(int32 $value) returns buf8 { my $toret = buf8.new(); $toret.append($value +& 0xFF); $toret.append(($value +> 8) +& 0xFF); $toret.append(($value +> 16) +& 0xFF); $toret } method assemble returns buf8 { my buf8 $toret = buf8.new(); $toret.write-uint8(0, $.op-code); $toret.write-uint8(1, $.operand, LittleEndian) if $.lenght == 2; $toret.write-uint16(1, $.operand, LittleEndian) if $.lenght == 3; $toret.append(self!encode-long($.operand)) if $.lenght == 4; $toret; }
 

The next step will be to test if the produced output is valid. So we will need to write tests and compare with other assemblers.

Feeds

FeedRSSLast fetchedNext fetched after
XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Bits of DNA XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
blogs.perl.org XML 12:00 AM, Tuesday, 18 January 2022 12:15 AM, Tuesday, 18 January 2022
Blue Collar Bioinformatics XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Boing Boing XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Epistasis Blog XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Futility Closet XML 12:00 AM, Tuesday, 18 January 2022 12:15 AM, Tuesday, 18 January 2022
gCaptain XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Hackaday XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
In between lines of code XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
InciWeb Incidents for California XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
LeafSpring XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Living in an Ivory Basement XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
LWN.net XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Mastering Emacs XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Planet Debian XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Planet Emacsen XML 12:00 AM, Tuesday, 18 January 2022 12:15 AM, Tuesday, 18 January 2022
RNA-Seq Blog XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
RStudio Blog - Latest Comments XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
RWeekly.org - Blogs to Learn R from the Community XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
The Adventure Blog XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
The Allium XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
Variance Explained XML 12:00 AM, Tuesday, 18 January 2022 12:30 AM, Tuesday, 18 January 2022
January 2022
MonTueWedThuFriSatSun
27282930310102
03040506070809
10111213141516
17181920212223
24252627282930
31010203040506
December 2021
MonTueWedThuFriSatSun
29300102030405
06070809101112
13141516171819
20212223242526
27282930310102
November 2021
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29300102030405
October 2021
MonTueWedThuFriSatSun
27282930010203
04050607080910
11121314151617
18192021222324
25262728293031
September 2021
MonTueWedThuFriSatSun
30310102030405
06070809101112
13141516171819
20212223242526
27282930010203
August 2021
MonTueWedThuFriSatSun
26272829303101
02030405060708
09101112131415
16171819202122
23242526272829
30310102030405
July 2021
MonTueWedThuFriSatSun
28293001020304
05060708091011
12131415161718
19202122232425
26272829303101
June 2021
MonTueWedThuFriSatSun
31010203040506
07080910111213
14151617181920
21222324252627
28293001020304
May 2021
MonTueWedThuFriSatSun
26272829300102
03040506070809
10111213141516
17181920212223
24252627282930
31010203040506
April 2021
MonTueWedThuFriSatSun
29303101020304
05060708091011
12131415161718
19202122232425
26272829300102
March 2021
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29303101020304
February 2021
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
November 2020
MonTueWedThuFriSatSun
26272829303101
02030405060708
09101112131415
16171819202122
23242526272829
30010203040506
September 2020
MonTueWedThuFriSatSun
31010203040506
07080910111213
14151617181920
21222324252627
28293001020304
July 2020
MonTueWedThuFriSatSun
29300102030405
06070809101112
13141516171819
20212223242526
27282930310102
June 2020
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29300102030405
May 2020
MonTueWedThuFriSatSun
27282930010203
04050607080910
11121314151617
18192021222324
25262728293031
April 2020
MonTueWedThuFriSatSun
30310102030405
06070809101112
13141516171819
20212223242526
27282930010203
February 2020
MonTueWedThuFriSatSun
27282930310102
03040506070809
10111213141516
17181920212223
24252627282901
January 2020
MonTueWedThuFriSatSun
30310102030405
06070809101112
13141516171819
20212223242526
27282930310102
December 2019
MonTueWedThuFriSatSun
25262728293001
02030405060708
09101112131415
16171819202122
23242526272829
30310102030405
November 2019
MonTueWedThuFriSatSun
28293031010203
04050607080910
11121314151617
18192021222324
25262728293001
October 2019
MonTueWedThuFriSatSun
30010203040506
07080910111213
14151617181920
21222324252627
28293031010203
August 2019
MonTueWedThuFriSatSun
29303101020304
05060708091011
12131415161718
19202122232425
26272829303101
July 2019
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29303101020304
June 2019
MonTueWedThuFriSatSun
27282930310102
03040506070809
10111213141516
17181920212223
24252627282930
May 2019
MonTueWedThuFriSatSun
29300102030405
06070809101112
13141516171819
20212223242526
27282930310102
April 2019
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29300102030405
March 2019
MonTueWedThuFriSatSun
25262728010203
04050607080910
11121314151617
18192021222324
25262728293031
February 2019
MonTueWedThuFriSatSun
28293031010203
04050607080910
11121314151617
18192021222324
25262728010203
January 2019
MonTueWedThuFriSatSun
31010203040506
07080910111213
14151617181920
21222324252627
28293031010203
December 2018
MonTueWedThuFriSatSun
26272829300102
03040506070809
10111213141516
17181920212223
24252627282930
31010203040506
November 2018
MonTueWedThuFriSatSun
29303101020304
05060708091011
12131415161718
19202122232425
26272829300102
October 2018
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29303101020304
September 2018
MonTueWedThuFriSatSun
27282930310102
03040506070809
10111213141516
17181920212223
24252627282930
August 2018
MonTueWedThuFriSatSun
30310102030405
06070809101112
13141516171819
20212223242526
27282930310102
July 2018
MonTueWedThuFriSatSun
25262728293001
02030405060708
09101112131415
16171819202122
23242526272829
30310102030405
June 2018
MonTueWedThuFriSatSun
28293031010203
04050607080910
11121314151617
18192021222324
25262728293001
May 2018
MonTueWedThuFriSatSun
30010203040506
07080910111213
14151617181920
21222324252627
28293031010203
April 2018
MonTueWedThuFriSatSun
26272829303101
02030405060708
09101112131415
16171819202122
23242526272829
30010203040506
February 2018
MonTueWedThuFriSatSun
29303101020304
05060708091011
12131415161718
19202122232425
26272801020304
January 2018
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29303101020304
December 2017
MonTueWedThuFriSatSun
27282930010203
04050607080910
11121314151617
18192021222324
25262728293031
November 2017
MonTueWedThuFriSatSun
30310102030405
06070809101112
13141516171819
20212223242526
27282930010203
September 2017
MonTueWedThuFriSatSun
28293031010203
04050607080910
11121314151617
18192021222324
25262728293001
August 2017
MonTueWedThuFriSatSun
31010203040506
07080910111213
14151617181920
21222324252627
28293031010203
March 2017
MonTueWedThuFriSatSun
27280102030405
06070809101112
13141516171819
20212223242526
27282930310102
January 2017
MonTueWedThuFriSatSun
26272829303101
02030405060708
09101112131415
16171819202122
23242526272829
30310102030405
November 2016
MonTueWedThuFriSatSun
31010203040506
07080910111213
14151617181920
21222324252627
28293001020304
October 2016
MonTueWedThuFriSatSun
26272829300102
03040506070809
10111213141516
17181920212223
24252627282930
31010203040506
September 2016
MonTueWedThuFriSatSun
29303101020304
05060708091011
12131415161718
19202122232425
26272829300102
August 2016
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29303101020304
July 2016
MonTueWedThuFriSatSun
27282930010203
04050607080910
11121314151617
18192021222324
25262728293031
May 2016
MonTueWedThuFriSatSun
25262728293001
02030405060708
09101112131415
16171819202122
23242526272829
30310102030405
April 2016
MonTueWedThuFriSatSun
28293031010203
04050607080910
11121314151617
18192021222324
25262728293001
December 2014
MonTueWedThuFriSatSun
01020304050607
08091011121314
15161718192021
22232425262728
29303101020304
October 2014
MonTueWedThuFriSatSun
29300102030405
06070809101112
13141516171819
20212223242526
27282930310102