The Boston Diaries
2024-03-09T22:05:14Z
http://boston.conman.org/
Sean Conner
sean@conman.org
https://www.conman.org/people/spc/
mod_blog
© 1999-2024 by Sean Conner. All Rights Reserved
tag:boston.conman.org,2024-03-01:/2024/03/01.1
The speed of Microsoft's BASIC floating point routines
2024-03-09T22:05:12Z
<P>I was curious about how fast <A CLASS="external" HREF="https://en.wikipedia.org/wiki/Microsoft_Binary_Format">Microsoft's <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> floating point</A> routines were.
This is easy enough to test,
now that I can <A CLASS="local" HREF="/2023/12/19.3">time assembly code inside the assembler</A>.
The code calculates -2π<SUP>3</SUP>/3! using Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> routines,
<ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 single precision and double precision.</P>
<P>First, Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR>:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
.tron timing
ms_fp ldx #.tau
jsr CB.FP0fx ; FP0 = .tau
ldx #.tau
jsr CB.FMULx ; FP0 = FP0 * .tau
ldx #.tau
jsr CB.FMULx ; FP0 = FP0 * .tau
jsr CB.FP1f0 ; FP1 = FP0
ldx #.fact3
jsr CB.FP0fx ; FP0 = 3!
jsr CB.FDIV ; FP0 = FP1 / FP0
neg CB.fp0sgn ; FP0 = -FP0
ldx #.answer
jsr CB.xfFP0 ; .answer = FP0
.troff
rts
.tau fcb $83,$49,$0F,$DA,$A2
.fact3 fcb $83,$40,$00,$00,$00
.answer rmb 5
fcb $86,$A5,$5D,$E7,$30 ; precalculated result
</PRE>
<P>I can't use the <CODE>.FLOAT</CODE> directive here since that only supports either the Microsoft format or <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 but not both.
So for this test,
I have to define the individual bytes per float.
The last line is what the result should be
(by checking a memory dump of the <ABBR TITLE="Virtual Machine">VM</ABBR> after running).
Also,
<CODE>.tao</CODE> is <A CLASS="external" HREF="https://tauday.com/tau-manifesto">2π</A>,
just in case that wasn't clear.
This ran in 8,742 cycles,
taking 2,124 instructions and 4.12 cycles per instruction
(I modified the assembler to record this additional information).</P>
<P>Next up,
<ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 single precision:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
.tron timing
ieee_single ldu #.tau
ldy #.tau
ldx #.answer
ldd #.fpcb
jsr REG
fcb FMUL ; .answer = .tau * .tau
ldu #.tau
ldy #.answer
ldx #.answer
ldd #.fpcb
jsr REG
fcb FMUL ; .answer = .answer * .tau
ldu #.answer
ldy #.fact3
ldx #.answer
ldd #.fpcb
jsr REG
fcb FDIV ; .answer = .answer / 3!
ldy #.answer
ldx #.answer
ldd #.fpcb
jsr REG
fcb FNEG ; .answer = -.answer
.troff
rts
.fpcb fcb FPCTL.single | FPCTL.rn | FPCTL.proj
fcb 0
fcb 0
fcb 0
fdb 0
.tau .float 6.283185307
.fact3 .float 3!
.answer .float 0
.float -(6.283185307 ** 3 / 3!)
</PRE>
<P>The floating point control block (<CODE>.fpcb</CODE>) configures the MC6839 to use single precision,
normal rounding and projective closure
(not sure what that is,
but it's the default value).
And it does calculate the correct result.
It's amazing that code written 42 <EM>years</EM> ago for an 8-bit <ABBR TITLE="Central Processing Unit">CPU</ABBR> works flawlessly.
What is <EM>isn't</EM> is fast.
This code took 14,204 cycles over 2,932 instructions (average 4.84 cycles per instruction).</P>
<P>The higher than average cycle type could be due to position independent addressing modes,
but I'm not entirely sure what it's doing to take nearly twice the time.
The <ABBR TITLE="Read Only Memory">ROM</ABBR> does use the <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 extended format (10 bytes) internally,
with more bit shifts to extract the exponent and mantissa,
but <EM>twice</EM> the time?</P>
<P>Perhaps it's code to deal with ±∞ and <ABBR TITLE="Not a Number">NaN</ABBR>s.</P>
<P>The <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 double precision is the same,
except for the floating point control block configuring double precision and the use of <CODE>.FLOATD</CODE> instead of <CODE>.FLOAT</CODE>;
otherwise the code is identical.
The result,
however,
isn't.
It took 31,613 cycles over 6,865 instructions (average 4.60 cycles per instruction).
And being twice the size,
it took nearly twice the time as single precision,
which is expected.</P>
<P>The final bit of code just loads the <ABBR TITLE="Read Only Memory">ROM</ABBR>s into memory,
and calls each function to get the timing:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
org $2000
incbin "mc6839.rom"
REG equ $203D ; register-based entry point
org $A000
incbin "bas12.rom"
.opt test prot rw,$00,$FF ; Direct Page for BASIC
.opt test prot rx,$2000,$2000+8192 ; MC6839 ROM
.opt test prot rx,$A000,$A000+8192 ; BASIC ROM
.test "BASIC"
lbsr ms_fp
rts
.endtst
.test "IEEE-SINGLE"
lbsr ieee_single
rts
.endtst
.test "IEEE-DOUBLE"
lbsr ieee_double
rts
.endtst
</PRE>
<P>Really,
the only surprising thing here was just how fast Microsoft <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> was at floating point.</P>
tag:boston.conman.org,2024-02-28:/2024/02/28.1
Converting IEEE-754 floating point to Color BASIC floating point
2024-03-02T02:46:01Z
<P>I'm still playing around with <A CLASS="local" HREF="/2024/02/07.1">floating point on the 6809</A>—specifically,
support for floating point for the Color Computer.
The format for floating point for Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR>
(written by Microsoft)
predates the <A CLASS="external" HREF="https://codedocs.org/what-is/ieee-754"><ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 Floating Point Standard</A> by a few years and thus,
isn't quite compatible.
It's close,
though.
It's defined as an 8-bit exponent,
biased by 129,
a single sign bit
(after the exponent)
and 31 bits for the mantissa
(the leading one assumed).
It also does <EM>not</EM> support ±∞ nor <ABBR TITLE="Not a Number">NaN</ABBR>.
This differs from the <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 single precision that uses a single sign bit,
an 8-bit exponent biased by 127 and 23 bits for the mantissa
(which also assumes a leafing one) and support for infinities and <ABBR TITLE="Not a Number">NaN</ABBR>.
The <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 double precision uses a single sign bit,
an 11-bit exponent biased by 1023 and 52 bit for the mantissa
(leading one assumed)
plus support for infinities and <ABBR TITLE="Not a Number">NaN</ABBR>.</P>
<P>So the Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> is about halfway between single precision and double precision.
This lead me to use <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 double precision for the Color Computer backend
(generating an error for inifinities and <ABBR TITLE="Not a Number">NaN</ABBR>)
<A CLASS="external" HREF="https://github.com/spc476/a09/blob/8682748ac0f98d7f83bbdb0b6e772270cf3fc89f/frsdos.c#L292">then massaging the resulting double into the proper format</A>.
I double checked this by finding some floating point constants in the Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> <ABBR TITLE="Read Only Memory">ROM</ABBR> as shown in the book <I>Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> Unravelled II</I>,
(<A CLASS="external" HREF="https://colorcomputerarchive.com/repo/Documents/Books/Unravelled%20Series/">available on the Computer Computer Archives</A>),
like this table:</P>
<PRE CLASS="language-Listing" TITLE="Listing">
4634 * MODIFIED TAYLOR SERIES SIN COEFFICIENTS
4635 BFC7 05 LBFC7 FCB 6-1 SIX COEFFICIENTS
4636 BFC8 84 E6 1A 2D 1B LBFC8 FCB $84,$E6,$1A,$2D,$1B * -((2*PI)**11)/11!
4637 BFCD 85 28 07 FB F8 LBFCD FCB $86,$28,$07,$FB,$F8 * ((2*PI)**9)/9!
4638 BFD2 87 99 68 89 01 LBFD2 FCB $87,$99,$68,$89,$01 * -((2*PI)**7)/7!
4639 BFD7 87 23 35 DF E1 LBFD7 FCB $87,$23,$35,$DF,$E1 * ((2*PI)**5)/5!
4640 BFDC 86 A5 5D E7 28 LBFDC FCB $86,$A5,$5D,$E7,$28 * -((2*PI)**3)/3!
4641 BFE1 83 49 0F DA A2 LBFE1 FCB $83,$49,$0F,$DA,$A2 * 2*PI
</PRE>
<P>Then using the byte values to populate a variable and printing it inside <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR>
(this is the expression -2π<SUP>3</SUP>/3!):</P>
<PRE CLASS="language-BASIC" TITLE="BASIC">
X=0 ' CREATE A VARIABLE
Y=VARPTR(X) ' GET ITS ADDRESS
POKE Y,&H86 ' AND SET ITS VALUE
POKE Y+1,&HA5 ' THE HARD WAY
POKE Y+2,&H5D
POKE Y+3,&HE7
POKE Y+4,&H28
PRINT X ' LET'S SEE WHAT IT IS
-41.3417023
</PRE>
<P>Then using that to create a floating point value:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
org $1000
.float -41.3417023
end
</PRE>
<P>Checking the resulting bytes that were generated:</P>
<PRE CLASS="language-Listing" TITLE="Listing">
| FILE ff.a
1 | org $1000
1000: 86A55DE735 2 | .float -41.3417023
3 | end
</PRE>
<P>And adjusting the floating point constant until I got bytes that matched:</P>
<PRE CLASS="language-Listing" TITLE="Listing">
| FILE ff.a
1 | org $1000
1000: 86A55DE728 2 | .float -41.341702110
3 | end
</PRE>
<P>I figure it's “close enough.”
The parsing code in the Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> <ABBR TITLE="Read Only Memory">ROM</ABBR> is old and predates the <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 floating point standard,
so a few different digits at the end I think is okay.</P>
<P>As a final check,
I wrote the following bit of code to calculate and display -2π<SUP>3</SUP>/3!,
display the pre-calculated result,
as well as display the pre-calculated value of 2π:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
include "Coco/basic.i"
include "Coco/dp.i"
CB.FSUBx equ $B9B9 ; FP0 = X - FP0 ; addresses for
CB.FSUB equ $B9BC ; FP0 = FP1 - FP0 ; these routines
CB.FADDx equ $B9C2 ; FP0 = X + FP0 ; from
CB.FADD equ $B9C5 ; FP0 = FP1 + FP1 ; Color BASIC Unravelled II
CB.FMULx equ $BACA ; FP0 = X * FP0
CB.FMUL equ $BAD0 ; FP0 = FP0 * FP1
CB.FDIVx equ $BB8F ; FP0 = X / FP0
CB.FDIV equ $BB91 ; FP0 = FP1 / FP0
CB.FP0fx equ $BC14 ; FP0 = X
CB.xfFP0 equ $BC35 ; X = FP0
CB.FP1f0 equ $BC5F ; FP1 = FP0
CB.FP0txt equ $BDD9 ; result in X, NUL terminated
org $4000
start ldx #tau ; point to 2*pi
jsr CB.FP0fx ; copy to FP0
ldx #tau ; 2PI * 2PI
jsr CB.FMULx
ldx #tau ; 2PI * 2PI * 2PI
jsr CB.FMULx
jsr CB.FP1f0 ; copy fp acc to FP1
ldx #fact3 ; point to 3!
jsr CB.FP0fx ; copy to FP0
jsr CB.FDIV ; FP0 = FP1 / FP0
neg CB.fp0sgn ; negate result by flippping FP0 sign
jsr CB.FP0txt ; generate string
bsr display ; display on screen
ldx #answer ; point to precalculated result
jsr CB.FP0fx ; copy to FP0
jsr CB.FP0txt ; generate string
bsr display ; display
ldx #tau ; now display 2*pi
jsr CB.FP0fx ; just to see how close
jsr CB.FP0txt ; it is.
bsr display
rts
display.char jsr [CHROUT] ; display character
display lda ,x+ ; get character
bne .char ; if not NUL byte, display
lda #13 ; go to next line
jsr [CHROUT]
rts
tau .float 6.283185307
fact3 .float 3!
answer .float -(6.283185307 ** 3 / 3!)
end start
</PRE>
<P>The results were:</P>
<PRE CLASS="language-data" TITLE="data">
-41.3417023
-41.3417023
6.23418531
</PRE>
<P>The calculation results in -41.3417023 and the direct result stored in <CODE>answer</CODE> also prints out -41.3417023,
so that matches and it reinforces my approach to this nominally right.</P>
<P>But I think Microsoft had issues with either generating some of the floating point constants for the larger terms,
or transcribing the byte values of the larger terms.
Take for instance -2π<SUP>11</SUP>/11!.
The correct answer is -15.0946426,
but the bytes in the <ABBR TITLE="Read Only Memory">ROM</ABBR> define the constant -14.3813907,
a difference of .7.
And it's not like Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> can't calculate that correctly—when I typed in the expression by hand,
it was able to come up with -15.0946426.</P>
<P>Or it could be that <DEL DATETIME="2024-03-01T18:46-0500">Walter K. Zydhek,</DEL> <INS DATETIME="2024-03-01T18:46-0500">the</INS>
author of <I>Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> Unravelled II</I>,
is wrong in his interpretation of the expressions used to generate the values,
or his interpretation of what the values are used for.
I'm not sure who is at fault here.</P>
<DIV CLASS="update">
<H4>Update on Friday, March 1<SUP>st</SUP>, 2024</H4>
<P>I was wrong about the authorship of <I>Color <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> Unravelled II</I>.
It was not Walter K. Zydhek,
but some unknown author of Spectral Associates,
a company that is no longer in business.
All Zydhek did was to transcribe a physical copy of the book (which is no longer available for purchase anywhere) into a <ABBR TITLE="Portable Document Format">PDF</ABBR> and make it available.</P>
</DIV>
tag:boston.conman.org,2024-02-14:/2024/02/14.1
Notes from an overheard conversation from a car attempting a right turn
2024-02-15T00:21:27Z
<P>“Oh! Now what?” </P>
<P>“Sir,
see the lit sign up there?
You cannot turn right.” </P>
<P>“But did you not see the car right in front of me turning right?” </P>
<P>“Sir,
if a person jumped off a bridge,
would you follow?” </P>
<P>“Yes.” </P>
<P>“You must be very smart then.” </P>
<P>“And selective enforcement of the laws leads to distrust of the police.” </P>
<P>“Sir—” </P>
<P>“Oh look! The ‘No Right Turn’ sign is off now!
Gotta go!
Bye!” </P>
<P>“I don't think it's wise to taunt the poice like that.” </P>
<P>“Down with the Man! Power to the people! Yo!” </P>
tag:boston.conman.org,2024-02-11:/2024/02/11.1
An extensible programming language
2024-02-12T02:33:08Z
<P>A few days ago <A CLASS="local" HREF="/2024/02/07.1">I wrote about adding a factorial operator to my assembler</A>,
and I noted that I knew not of any other languages that had such a feature.
So imagine my surprise as I'm reading about <A CLASS="external" HREF="https://xlr.sourceforge.io/"><ABBR TITLE="eXtensible Language">XL</ABBR></A>
(via <A CLASS="external" HREF="https://lobste.rs/s/zu2wx1/xl_extensible_programming_language">Lobsters</A>)
and the <A CLASS="external" HREF="https://xlr.sourceforge.io/#factorial">second example is factorial</A>!
Not only that,
but that was an example of <EM>extending the language itself!</EM>
The last time I was this excited about software was reading about <A CLASS="external" HREF="https://web.archive.org/web/20080318162920/http://valhenson.org/synthesis/SynthesisOS/abs.html">Synthesis <ABBR TITLE="Operating System">OS</ABBR></A>,
a <A CLASS="external" HREF="https://en.wikipedia.org/wiki/Self-modifying_code#Synthesis"><ABBR TITLE="Just-In-Time">JIT</ABBR>-based operating system where you could create your own system calls</A>.</P>
<P>How it handles precedence is interesting.
In my <A CLASS="external" HREF="https://github.com/spc476/a09">assembler</A>,
I have left or right associativity as an <A CLASS="external" HREF="https://github.com/spc476/a09/blob/main/expr.c#L337">explicit field</A>,
whereas in <ABBR TITLE="eXtensible Language">XL</ABBR>,
it's encoded in the <A CLASS="external" HREF="https://xlr.sourceforge.io/#operator-precedence-and-associativity">precedence level itself</A>—even if its left,
odd if its right.
I'm not sure how I feel about that.
On the one hand it feels nice and it's one less field to carry around;
on the other,
being explicit as I did makes it clear if something is left or right.
But on the gripping hand,
it sounds like matching precedence on a left and right operator could lead to problems,
so I still may have an explicitness problem.</P>
<P>But I digress.</P>
<P>It's a very simple language with only one keyword “is” and a user-definable precedence table.
The parser generates a parse tree of only eight types,
four leaf nodes (integer, real, text, name (or symbol))
and four non-leaf nodes (prefix, infix, postfix and block).
And from there,
you get <ABBR TITLE="eXtensible Language">XL</ABBR>.</P>
<P>This is something I definitely want to <A CLASS="external" HREF="https://github.com/c3d/xl">look into</A>.</P>
tag:boston.conman.org,2024-02-07:/2024/02/07.1
Instead of “write-only memory” assembly support, how about floating point support?
2024-02-08T04:15:29Z
<P>You might think it odd to add support for floating point constants for an 8-bit CPU,
but Motorola did development on the MC6839 floating point firmware for the MC6809,
an 8K <ABBR TITLE="Read-Only Memory">ROM</ABBR> of thread-safe, position-independent 6809 code that implements the <A CLASS="external" HREF="https://en.wikipedia.org/wiki/IEEE_754"><ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR> Standard for Floating-Point Arithmetic</A>.
It was never formally released by Motorola as a product,
but from what I understand,
it was released later under a public domain license.
At the very least,
it's quite easy to <A CLASS="external" HREF="https://github.com/brouhaha/fp09">MC6839 find both the <ABBR TITLE="Read-Only Memory">ROM</ABBR> image and the source code</A> on the Intarwebs.
So that's one reason.</P>
<P>Another reason is that the Color Computer <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> supports floating point operations,
and while not <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754,
as it was written before the <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754 standard become a standard,
it still floating point,
and there are only minor differences between it and the current standard,
namely the exponent bias,
number of fractional bits supported,
and where the sign bit is stored.
It really comes down to some bit manipulations to massage a standard float into the Color Computer <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> float format.
There are some differences,
but the differences are small
(literally,
on the scale of 0.0000003)
probably due to parsing differences,
and small enough that it should be “good enough.”
Especially since the Color Computer <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> float format doesn't support infinity or <ABBR TITLE="Not a Number">NaN</ABBR>.</P>
<P>So if you specify a backend <EM>other</EM> than the <CODE>rsdos</CODE> backend,
you get <ABBR TITLE="Institute of Electrical and Electronics Engineers">IEEE</ABBR>-754,
and if you do specify <CODE>rsdos</CODE> as a backend,
you get the Color Computer <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> float format.</P>
<P>And yes,
I added support for floating point expressions
(but <EM>not</EM> for the test backend—I'm still thinking on how to support it),
and one interesting feature I added is the factorial operator “!”.
Factorials are used in <A CLASS="external" HREF="https://en.wikipedia.org/wiki/Taylor_series">Talor series</A>,
which the Color Computer <ABBR TITLE="Beginners' All-purpose Symbolic Instruction Code">BASIC</ABBR> uses for the <CODE>sin()</CODE> function,
so I can literally write:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
; Oh! '**' is exponentiation by the way!
taylor_series .float -((2 * 3.14159265358979323846) ** 11) / 11!
.float ((2 * 3.14159265358979323846) ** 9) / 9!
.float -((2 * 3.14159265358979323846) ** 7) / 7!
.float ((2 * 3.14159265358979323846) ** 5) / 5!
.float -((2 * 3.14159265358979323846) ** 3) / 3!
.float 2 * 3.14159265358979323846
</PRE>
<P>and have it generate the correct values.
I personally don't know of any language that has a factorial operator
(maybe APL?
I don't know).</P>
<P>I think I'm having more fun writing the assembler than I am writing assembly code.</P>
tag:boston.conman.org,2024-02-06:/2024/02/06.2
Okay! I'll answer your question, LinkedIn. Also, Orange Site! Orange Site! Orange Site!
2024-02-07T02:47:36Z
<P>Today's “<A CLASS="local" HREF="/2024/01/31.2">you're one of the few experts invited to add this collaborative article</A>” from <A CLASS="external" HREF="https://www.linked.com/">LinkedIn</A> is
“How do you become a senior application developer?”
My answer?
Stay in a programming job for three years.
Boom!
You're a senior application developer.
I know,
I know,
that's a big ask these days when everybody is jumping ship every two years.
But hey,
if you want to be a “senior application developer,”
you got to make sacrifices.</P>
<P>Oh,
and the title to today's post?
I found out that LinkedIn <EM>really liked</EM> when I mentioned <A CLASS="external" HREF="https://news.ycombinator.com/">the Orange Site</A> in the title of my post.
Almost two orders of magnitude more.
So I'm doing a test to see if I can game the system there.</P>
tag:boston.conman.org,2024-02-06:/2024/02/06.1
So you want to amplify my SEO
2024-02-07T00:09:01Z
<BLOCKQUOTE>
<DL CLASS="header">
<DT>From</DT><DD> Krystal <SPAN CLASS="cut">XXXXXXX</SPAN> <<SPAN CLASS="cut">XXXXXXXXXXXXXXXXXXXX</SPAN>@gmail.com></DD>
<DT>To</DT><DD> sean@conman.org</DD>
<DT>Subject</DT><DD> Amplify Your <ABBR TITLE="Search Engine Optimization">SEO</ABBR> with Strategic Link Inserts</DD>
<DT>Date</DT><DD> Wed, 7 Feb 2024 01:16:35 +0300</DD>
</DL>
<P>Hi Content Team,</P>
<P>It’s Krystal <SPAN CLASS="cut">XXXXXXX</SPAN> here from Next Publisher, your next potential partner
in digital storytelling. We're thrilled about the idea of featuring both
guest posts and link insertions on your dynamic website.</P>
<P>We would like to know your fee structure for hosting guest posts and link
insertions. Our team aims to create compelling content that is tailored to
your site’s audience and enhances your overall content strategy.</P>
<P>A quick note: this initial email is only for starting our dialogue. All
more detailed communications, including agreements and transactions, will
be carried out through our official Next Publisher email.</P>
<P>We admire the quality of your platform and are excited to explore how we
can work together for mutual benefit.</P>
<P>Looking forward to your prompt reply.</P>
<P>Warm wishes,</P>
<P>Krystal <SPAN CLASS="cut">XXXXXXX</SPAN>
</BLOCKQUOTE>
<P>Hello Krystal.</P>
<P>Since you neglected to include a link
(in an email sent as <ABBR TITLE="HyperText Markup Language">HTML</ABBR> no less!)
it's hard for me judge the value Next Publisher will provide for my site,
so I'm going to have to adjust my prices accordingly.
My fee for both guest posts and link insertions is $10,000 (<ABBR TITLE="United States">US</ABBR>) per.
So if a guest post also includes a link insertion,
that would be a total of $20,000 (<ABBR TITLE="United States">US</ABBR>).
If I'm going to be <DEL>whoring</DEL> selling out what <A CLASS="external" HREF="https://en.wikipedia.org/wiki/PageRank">Google Page Rank</A> I have,
it's going to cost.</P>
<P>I look forward to hearing back from you.</P>
<P>Sean.</P>
tag:boston.conman.org,2024-02-05:/2024/02/05.1
The difficulties in supporting “write-only memory” in assembly
2024-02-06T02:01:11Z
<P>When I <A CLASS="local" HREF="/2024/01/31.3">last wrote about this</A>,
I had one outstanding problem with static analysis of read-only/write-only memory,
and that was with hardware that could be input <EM>or</EM> output only.
It was only after I wrote that that I realized the solution—it's the same as a hardware register having different semantics on read vs. write—just define <EM>two</EM> labels with the semantics I want.
So for the <A CLASS="external" HREF="https://en.wikipedia.org/wiki/Peripheral_Interface_Adapter">MC6821</A>,
I could have:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
org $FF00
PIA0.A rmb/r 1 ; read only
org $FF00
PIA0.Adir rmb/w 1 ; write only, to set the direction of each IO pin
PIA0.Acontrol rmb 1 ; control for port A
</PRE>
<P>So that was a non-issue.
It was then I started looking over some existing code I had to see how it might look.
I didn't want to just jump into an implementation without some forethought,
and I quickly found some issues with the idea by looking at my <A CLASS="local" HREF="/2023/11/27.1">maze generation program</A>.
The code in question initializes the required video mode
(in this case 64×64 with four colors).
Step one involves writing a particular value to the MC6821:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
lda #G1C.PIA ; 64x64x4
sta PIA1.B
</PRE>
<P>So far so good. I can mark <CODE>PIA1.B</CODE> as write-only
(technically, it also has some input pins so I really can't,
but in <EM>theory</EM> I could).</P>
<P>Now,
the next bit requires some explaining.
There's another 3-bit value that needs to be configured on the <A CLASS="external" HREF="https://archive.org/details/Motorola_MC6883_Synchronous_Address_Multiplexer_Advance_Sheet_19xx_Motorola">MC6883</A>,
but it's not as simple as writing the 3-bit value to a hardware register—each <EM>bit</EM> requires writing to a different address,
and worse—it's a different address if the bit is 0 or 1.
So that's six different addresses required.
It's not horrible though—the addresses are sequential:</P>
<TABLE>
<CAPTION>6883 <ABBR TITLE="Video Display Generator">VDG</ABBR> Addressing Mode</CAPTION>
<THEAD>
<TR><TH>bit</TH> <TH>0/1</TH> <TH>address</TH></TR>
</THEAD>
<TBODY>
<TR><TD><CODE>V0</CODE></TD> <TD CLASS="num">0</TD> <TD><CODE>$FFC0</CODE></TD></TR>
<TR><TD><CODE>V0</CODE></TD> <TD CLASS="num">1</TD> <TD><CODE>$FFC1</CODE></TD></TR>
<TR><TD><CODE>V1</CODE></TD> <TD CLASS="num">0</TD> <TD><CODE>$FFC2</CODE></TD></TR>
<TR><TD><CODE>V1</CODE></TD> <TD CLASS="num">1</TD> <TD><CODE>$FFC3</CODE></TD></TR>
<TR><TD><CODE>V2</CODE></TD> <TD CLASS="num">0</TD> <TD><CODE>$FFC4</CODE></TD></TR>
<TR><TD><CODE>V2</CODE></TD> <TD CLASS="num">1</TD> <TD><CODE>$FFC5</CODE></TD></TR>
</TBODY>
</TABLE>
<P>Yeah,
to a software programmer,
hardware can be weird.
To set bit 0 to 0,
you do a write
(and it does not matter what the value is)
to address <CODE>$FFC0</CODE>.
If bit 0 is 1,
then it's a write to <CODE>$FFC1</CODE>.
So with that in mind,
I have:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
sta SAM.V0 + (G1C.V & 1<<0 <> 0)
sta SAM.V1 + (G1C.V & 1<<1 <> 0)
sta SAM.V2 + (G1C.V & 1<<2 <> 0)
</PRE>
<P>OOh.
Yeah.</P>
<P>I wrote it this way so I wouldn't have to look up the appropriate value and write the more opaque
(to me):</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
sta $FFC1
sta SFFC2
sta $FFC4
</PRE>
<P>The expression <CODE>(G1C.V & 1<<n <> 0)</CODE> checks bit n to see if it's set or not,
and returns 0 (for not set) or 1 (for set).
This is then added to the base address for bit n,
and it all works out fine. I can change the code for,
say, the 128×192 four color mode by using a different constant:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
lda #G6C.PIA
sta PIA1.B
sta SAM.V0 + (G6C.V & 1<<0 <> 0)
sta SAM.V1 + (G6C.V & 1<<1 <> 0)
sta SAM.V2 + (G6C.V & 1<<2 <> 0)
</PRE>
<P>But I digress.</P>
<P>This is a bit harder to support.
The address being written is part of an expression,
and only the label (defining the address) would have the read/write attribute associated with it.
At least,
that was my intent.
I suppose I could track the read/write attribute by address,
which would solve this particular segment of code.</P>
<P>And the final bit of code to set the address of the video screen
(or frame buffer):</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
ldx #SAM.F6 ; point to frame buffer address bits
lda ECB.grpram ; get MSB of frame buffer
mapframebuf clrb
lsla
rolb
sta b,x ; next bit of address
leax -2,x
cmpx #SAM.F0
bhs mapframebuf
</PRE>
<P>Like the <ABBR TITLE="Video Display Generator">VDG</ABBR> Address Mode bits,
the bits for the <ABBR TITLE="Video Display Generator">VDG</ABBR> Address Offset have unique addresses,
and because the <ABBR TITLE="Video Display Generator">VDG</ABBR> Address Offset has seven bits,
the address is aligned to a 512 byte boundary.
Here,
the code loads the <CODE>X</CODE> register with the address of the upper end of the <ABBR TITLE="Video Display Generator">VDG</ABBR> Address Offset,
and the seven top most bits of the video address is sent,
one at a time,
to the <CODE>B</CODE> register,
which is used as an offset to the <CODE>X</CODE> register to set the appropriate address for the appropriate bit.
So now I would have to track the read/write attributes via the index registers as well.</P>
<P>That is not so easy.</P>
<P>I mean,
here,
it could work,
as the code is all in one place,
but what if instead it was:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
ldx #SAM.F6
lda ECB.grpram
jsr mapframebuf
</PRE>
<P>Or an even worse example:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
costmessage fcc/r "A constant message" ; read only text
buffer rmb 18
ldx #constmessage
ldy #buffer
lda #18
jsr memcpy
</PRE>
<P>The subroutine <CODE>memcpy</CODE> might not even be in the same source unit,
so how would the read/write attribute even be checked?
This is for static analysis,
not runtime.</P>
<P>I have one variation on the maze generation program that generates multiple mazes at the same time,
on the same screen
(it's fun to watch)
and as such,
I have the data required for each “maze generator” stored in a structure:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
explorec equ 0 ; read-only
backtrackc equ 1 ; read-only
xmin equ 2 ; read-only
ymin equ 3 ; read-only
xstart equ 4 ; read-only
ystart equ 5 ; read-only
xmax equ 6 ; read-only
ymax equ 7 ; read-only
xpos equ 8 ; read-write
ypos equ 9 ; read-write
color equ 10 ; read-write
func equ 11 ; read-write
</PRE>
<P>This is from the source code,
but I've commented each “field” as being “read-only” or “read-write.”
That's <EM>another</EM> aspect of this that I didn't consider:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
lda explorec,x ; this is okay
sta explorec,x ; this is NOT okay
</PRE>
<P>Not only would I have to track read/write attributes for addresses,
but for field accesses to a structure as well.
I'm not saying this is impossible,
it's just going to take way more thought than I thought.
I don't think I'll have this feature done any time soon … </P>
tag:boston.conman.org,2024-02-02:/2024/02/02.4
It should be obvious by now what day it is, but just in case
2024-02-03T02:30:49Z
<P>I want to ensure everybody that yes,
I intentionally made the previous three posts.
And while they are similar,
they are <EM>not</EM> in fact,
identical.
You know,
much like <A CLASS="external" HREF="https://en.wikipedia.org/wiki/Groundhog_Day_(film)">Ground Hog Day</A>.</P>
tag:boston.conman.org,2024-02-02:/2024/02/02.3
Making it to the Orange Site
2024-02-03T02:30:42Z
<P>A <A CLASS="local" HREF="/2024/01/31.3">previous post</A> made it to <A CLASS="external" HREF="https://lobste.rs/s/ulfdn2">Lobster</A> only to later show up at <A CLASS="external" HREF="https://news.ycombinator.com/item?id=39226345">the Orange Site</A>.
How about that?</P>
tag:boston.conman.org,2024-02-02:/2024/02/02.2
Making it to the Orange Site
2024-02-03T02:30:35Z
<P>A <A CLASS="local" HREF="/2024/01/31.3">previous post</A> made it to <A CLASS="external" HREF="https://lobste.rs/s/ulfdn2">Lobster</A> only to later show up at <A CLASS="external" HREF="https://news.ycombinator.com/item?id=39221849">the Orange Site</A>.
How about that?</P>
tag:boston.conman.org,2024-02-02:/2024/02/02.1
Making it to the Orange Site
2024-02-03T02:30:29Z
<P>A <A CLASS="local" HREF="/2024/01/31.3">previous post</A> made it to <A CLASS="external" HREF="https://lobste.rs/s/ulfdn2">Lobster</A> only to later show up at <A CLASS="external" HREF="https://news.ycombinator.com/item?id=39212958">the Orange Site</A>.
How about that?</P>
tag:boston.conman.org,2024-01-31:/2024/01/31.4
How much for the book? I don't think I paid that much for the computer
2024-02-01T05:23:56Z
<P>Now,
about that <A CLASS="book" HREF="https://www.amazon.com/exec/obidos/ASIN/0201181576/conmanlaborat-20">Amiga Hardware Reference Manual</A> link in my <A CLASS="local" HREF="/2024/01/31.3">previous post</A>—<EM>$577.99‽</EM> </P>
<P><EM>Seriously‽</EM> </P>
<P>I know it's now a niche market,
but are there really people <EM>buying</EM> that book for almost $600?</P>
<P>Good Lord!</P>
tag:boston.conman.org,2024-01-31:/2024/01/31.3
I know languages that have support for “read-only memory,” but what about “write-only memory?”
2024-02-01T09:53:09Z
<P>I'm still hacking away on my <A CLASS="external" HREF="https://github.com/spc476/a09">overengineered 6809 assembler</A> and one feature I've beem mulling over is a form of static access checking.
I have <A CLASS="local" HREF="/2024/01/19.1">byte-level access control when running tests</A> but I'm thinking that adding some form of “assemble time checking” would also be good.
I've been writing code hitting the hardware of the Color Computer,
and there are semantics around hardware that I don't think many languages
(or even assembler)
support—<EM>write only memory!</EM>
As the <A CLASS="book" HREF="https://www.amazon.com/exec/obidos/ASIN/0201181576/conmanlaborat-20">Amiga Hardware Reference Manual</A> states
(only referenced here because it's a good example of what I'm talking about):</P>
<BLOCKQUOTE>
<P>Registers are either <EM>read-only</EM> or <EM>write-only.</EM> Reading a write-only register will trash the register.
Writing a read-only register will cause unexpected results.</P>
<P>… </P>
<P>When strobing any register which responds to either a read or a write, (for example <VAR>copjmp2</VAR>) be sure
to use a <CODE>MOVE.W</CODE>, not <CODE>CLR.W</CODE>. The <CODE>CLR</CODE> instruction causes a read and a clear (two access) on a 68000,
but only a single access on 68020 processors. This will give different results on different processors.</P>
</BLOCKQUOTE>
<P>The Color Computer isn't quite as finicky
(although the 6809 inside it also does the “read, then write” thing with the <CODE>CLR</CODE> instruction),
but there is still memory-mapped <ABBR TITLE="Input/Output">IO</ABBR> that is read-only, some that is write-only,
and some that has different meanings when reading and writing.
And while C has some semantic support with <CODE>volatile</CODE>
(to ensure reads and writes happen when stated)
and <CODE>const</CODE>
(to ensure the read-only nature)
it still lacks a “write-only” concept.
And I've never used an assembler that had “write-only” semantics either.</P>
<P>I'm thinking something along these lines:</P>
<PRE CLASS="language-Assembly" TITLE="Assembly">
org $FF40
DSK.CTRL rmb/w 1 ; write only
org $FF48
DSK.CMD rmb/w 1 ; write only
org $FF48
DSK.STATUS rmb/r 1 ; read only
DSK.TRACK rmb 1 ; these can be read and written
DSK.SECTOR rmb 1
DSK.DATA rmb 1
</PRE>
<P>Here, the <CODE>RMB</CODE> directive just reserves a number of bytes, with a default access of “read-write.”
The <CODE>/W</CODE> or <CODE>/R</CODE> designates that label as being either “write-only” or “read-only.”
And if you look closely,
you'll see that both <CODE>DSK.CMD</CODE> and <CODE>DSK.STATUS</CODE> are defined as the same address.
It's just that writing to that address will send a command to the drive controller,
while reading from that address give the current status.
The only issue I have are hardware registers that can be programmed for input <EM>or</EM> output.
The <A CLASS="external" HREF="https://en.wikipedia.org/wiki/Peripheral_Interface_Adapter">MC6821</A> used in the Color Computer has such registers,
and the issue I have is how to signify this change in state in a program—that at <EM>this</EM> point in the program,
such-n-such address is “read-write” but afterwards, it's “write-only.” </P>
tag:boston.conman.org,2024-01-31:/2024/01/31.2
Dear LinkedIn, I don't think I'm the expert you want answering these questions
2024-02-01T06:02:36Z
<P>I cross post links to my blog on <A CLASS="external" HREF="https://www.linked.com/">LinkedIn</A> mainly to be contrarian,
or at least think I'm providing something <EM>different</EM> than all the business related stuff posted there.
But lately,
I've seen notifications there like,
“You're <STRONG>one of the few experts</STRONG> invited to add this collaborative article: …” and it's some article about <A CLASS="local" HREF="/2024/01/08.1"><ABBR TITLE="Artificial Ingelligence">AI</ABBR></A>,
or <A CLASS="local" HREF="/2022/02/11.1">Agile</A> or the latest one,
“Your team is falling behind on project deadlines. What web-based tools can help you catch up?”
<P>Oh … nothing good can come from me answering these questions.</P>
<!--
<p>I'm tempted.
Lord,
I'm tempted to “contribute” but I'm afraid that my replies might not be … <em>appreciated</em> let's just say.
At least,
reply on LinkedIn.
Here?
Let's go!</p>
<ol>
<li>“Project Mangement Software?”
Our team is late—we need to learn how to say “No.”
We need to push back on unrealistic dead lines.
Or at least,
our manager should be doing those things.</li>
<li>“Communication tools?”
Email?
A white board?
Phone?
We already have a ton of communication tools.
Lord knows we don't need <em>more</em> at this time.</li>
<li>“Time tracking tools?”
What's exactly wrong with “nine to five?”
Well,
I suppose we could track the time the developers are spending in useless meetings <em>not working on the project.</em>
That would be a cool <abbr title="Key Performance Indicator">KPI</abbr> to show upper management.</li>
<li>“Testing tools?”
Aren't we already using testing tools?
How did we ever manage back in the 90s?</li>
<li>“Feebback tools?”
Isn't this redundant with #2?
Or do you mean <del>yelling at the idiots</del> calm discussions with upper managmement?
Wait!
I thought this was what our manager should be doing.</li>
<li>“Learning tools.”
Oh, we're learning alright,
just not what you think we're learning.</li>
<li>“Here's what else to consider.”
Perhaps leave the developers to work out a programing paradigm that works for them and let them have time to do the work?
Perhaps treat developers like professionals doing their job without micromanagement?
No?
Oh.</li>
</ol>
<p>Yeah,
I don't think these are the answers LinkedIn is looking for.</p>
-->