Discussion:
Here's a MACRO-11 question...
(too old to reply)
Lee Gleason
2022-01-14 16:18:49 UTC
Permalink
I've been writing some stand alone (no OS) MACRO-11 code lately, that
has some sections that need longword alignment.

Word alignment would be easy....a .EVEN directive would take care of
it. But there's no .LONG in MACRO-11.

I reckon I can do some location counter arithmetic to get it done,
but I'm wondering if there's already a known solution for this.

--
Lee K. Gleason N5ZMR
Control-G Consultants
***@comcast.net
Bob Eager
2022-01-14 17:12:56 UTC
Permalink
Post by Lee Gleason
I've been writing some stand alone (no OS) MACRO-11 code lately, that
has some sections that need longword alignment.
Word alignment would be easy....a .EVEN directive would take care of
it. But there's no .LONG in MACRO-11.
I reckon I can do some location counter arithmetic to get it done,
but I'm wondering if there's already a known solution for this.
I've always done it with location counter arithmetic.
--
Using UNIX since v6 (1975)...

Use the BIG mirror service in the UK:
http://www.mirrorservice.org
Johnny Billquist
2022-01-14 17:23:10 UTC
Permalink
  I've been writing some stand alone (no OS) MACRO-11 code lately, that
has some sections  that need longword alignment.
  Word alignment would be easy....a .EVEN directive would take care of
it. But there's no .LONG in MACRO-11.
  I reckon I can do some location counter arithmetic to get it done,
but I'm wondering if there's already a known solution for this.
The problem is that unless you make sure all sections are longword
aligned, you hit the problem that TKB is in the end the thing
responsible, and it tries to pack things as much as possible.

And while it's pretty straight forward in theory, I can't create such a
padding in MACRO-11. The problem is that I'm not allowed to do that kind
of arithmetic on the current location, as it is a relative value.
But maybe I'm just not creative enough right at this moment.

But with that said, I do have a MACRO-11 definition of .LONG which works
just fine. :-)

Johnny
Lee Gleason
2022-01-14 20:55:15 UTC
Permalink
Post by Johnny Billquist
And while it's pretty straight forward in theory, I can't create such a
padding in MACRO-11. The problem is that I'm not allowed to do that kind
of arithmetic on the current location, as it is a relative value.
But maybe I'm just not creative enough right at this moment.
But with that said, I do have a MACRO-11 definition of .LONG which works
just fine. :-)
  Johnny
Care to share it?

--
Lee K. Gleason N5ZMR
Control-G Consultants
***@comcast.net
Don North
2022-01-15 02:38:58 UTC
Permalink
Post by Johnny Billquist
And while it's pretty straight forward in theory, I can't create such a
padding in MACRO-11. The problem is that I'm not allowed to do that kind of
arithmetic on the current location, as it is a relative value.
But maybe I'm just not creative enough right at this moment.
But with that said, I do have a MACRO-11 definition of .LONG which works just
fine. :-)
   Johnny
FYI I made up this macro for MACRO-11 that aligns the current location counter
such that the 'arg1' low bits are zeroes.

'arg1' can be 1 for word, 2 for longword, 3 for quadword, etc.

HOWEVER the alignment is relative to the start of the current program/data
section, which the linker normally only word aligns. So I only use it in
absolute sections where I can set the starting address to 0, 1000(8), etc.

.macro align arg1
.nlist
$$pos=1
.rept arg1
.if ne <.&$$pos>
.blkb $$pos
.endc
$$pos=$$pos*2
.endr
.list
.endm align
Lee Gleason
2022-01-15 21:30:57 UTC
Permalink
Post by Don North
FYI I made up this macro for MACRO-11 that aligns the current location counter
such that the 'arg1' low bits are zeroes.
'arg1' can be 1 for word, 2 for longword, 3 for quadword, etc.
HOWEVER the alignment is relative to the start of the current
program/data section, which the linker normally only word aligns. So I
only use it in absolute sections where I can set the starting address to
0, 1000(8), etc.
.macro    align    arg1
.nlist
    $$pos=1
.rept    arg1
.if ne <.&$$pos>
    .blkb    $$pos
.endc
    $$pos=$$pos*2
.endr
.list
.endm    align
Thanks!

--
Lee K. Gleason N5ZMR
Control-G Consultants
***@comcast.net
Jonathan Harston
2022-01-16 18:11:12 UTC
Permalink
If your assembler has an 'insert string' directive which takes
parameters, it's fairly simple, something like:

DS length,fillbyte
DS (($+3) BINARYAND -4)-$, 0

to align to a multiple of 4, as a general case of:

DS (($+num-1) BINARYAND -num)-$,0

where num is a power of two and $ is the location counter.
Bob Eager
2022-01-16 21:46:29 UTC
Permalink
Post by Jonathan Harston
If your assembler has an 'insert string' directive which takes
DS length,fillbyte DS (($+3) BINARYAND -4)-$, 0
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
Pretty sure I used to use someting like:

.=(.+3)&4
--
Using UNIX since v6 (1975)...

Use the BIG mirror service in the UK:
http://www.mirrorservice.org
Jonathan Harston
2022-01-16 23:03:52 UTC
Permalink
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
What does that do to the memory between current . and new . ?
In may assemblers I found it was unassigned, so I used an explicit
memory-filling directive, particularly after somebody pointed out
the random unassigned locations made binary diffs fiddlier as you
would almost always get differences reported.

In the PDP11 assembler wot i rote I implemented (and, importantly,
documented) an ALIGN directive as explicitly filling with zeros.

jgh
Bob Eager
2022-01-17 00:07:02 UTC
Permalink
Post by Jonathan Harston
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
What does that do to the memory between current . and new . ?
I didn't care.
--
Using UNIX since v6 (1975)...

Use the BIG mirror service in the UK:
http://www.mirrorservice.org
Don North
2022-01-17 01:41:58 UTC
Permalink
Post by Jonathan Harston
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
What does that do to the memory between current . and new . ?
In may assemblers I found it was unassigned, so I used an explicit
memory-filling directive, particularly after somebody pointed out
the random unassigned locations made binary diffs fiddlier as you
would almost always get differences reported.
In the PDP11 assembler wot i rote I implemented (and, importantly,
documented) an ALIGN directive as explicitly filling with zeros.
I think you meant to write: .=(.+3)&(-4)
as your expression only generates the values of 0 or 4 for the new '.'.

As to the fill for unused locations, the PDP-11 linker won't place
anything in the unreferenced locations and won't refer to them.

So any binary difference checker on generated object or load files
should still compare. Once you load the program into actual memory
of course whatever exists there will stay there, unchanged.
Bob Eager
2022-01-17 09:05:48 UTC
Permalink
Post by Don North
Post by Jonathan Harston
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
What does that do to the memory between current . and new . ?
In may assemblers I found it was unassigned, so I used an explicit
memory-filling directive, particularly after somebody pointed out the
random unassigned locations made binary diffs fiddlier as you would
almost always get differences reported.
In the PDP11 assembler wot i rote I implemented (and, importantly,
documented) an ALIGN directive as explicitly filling with zeros.
I think you meant to write: .=(.+3)&(-4)
as your expression only generates the values of 0 or 4 for the new '.'.
Yes, thanks! It was off the top of my head and I didn't have anything tp
try it on. Didn't help that I am currently writing an assembler for a
completely differemt syntax!
--
Using UNIX since v6 (1975)...

Use the BIG mirror service in the UK:
http://www.mirrorservice.org
Johnny Billquist
2022-01-17 17:56:16 UTC
Permalink
Post by Jonathan Harston
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
What does that do to the memory between current . and new . ?
In may assemblers I found it was unassigned, so I used an explicit
memory-filling directive, particularly after somebody pointed out
the random unassigned locations made binary diffs fiddlier as you
would almost always get differences reported.
In the PDP11 assembler wot i rote I implemented (and, importantly,
documented) an ALIGN directive as explicitly filling with zeros.
I think you meant to write:   .=(.+3)&(-4)
as your expression only generates the values of 0 or 4 for the new '.'.
Yeah. Don just got it slightly wrong. :-)
But I would have written it as:
. = (. + 3) & ^C3

(Where ^C means ones complement in Macro-11.)
As to the fill for unused locations, the PDP-11 linker won't place
anything in the unreferenced locations and won't refer to them.
Right.
So any binary difference checker on generated object or load files
should still compare. Once you load the program into actual memory
of course whatever exists there will stay there, unchanged.
Not entirely sure about load file. Depends on which format it is in.
.LDA would do as you say, I think. TSK would not. Since it can only
describe one memory chunk in this case. (I'm assuming a load file with
no additional OS related stuff. A TSK file can be either, and with OS
related stuff also comes the capability of having multiple memory chunks
if I remember right...)

Johnny
Don North
2022-01-18 00:17:16 UTC
Permalink
Post by Johnny Billquist
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
Yeah. Don just got it slightly wrong. :-)
. = (. + 3) & ^C3
(Where ^C means ones complement in Macro-11.)
Well actually we both got it ~slightly~ wrong ... the correct syntax:

. = <. + 3> & ^C3

which as pointed out ONLY works in absolute PSECTs.
Throws an error in relative PSECTs.
Johnny Billquist
2022-01-18 00:36:30 UTC
Permalink
Post by Johnny Billquist
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
Yeah. Don just got it slightly wrong. :-)
. = (. + 3) & ^C3
(Where ^C means ones complement in Macro-11.)
  . = <. + 3> & ^C3
Of course. I wasn't thinking about getting it MACRO-11 correct.
Initially I even wrote (. + 3) & ~3, but then I figured that maybe using
~ for negation might not be understood by everyone, so I started
MACRO-11:fying it a little. :-)
which as pointed out ONLY works in absolute PSECTs.
Throws an error in relative PSECTs.
Yeah. That is my main issue/problem. I'd like to have one that works in
relative psects. Even though it's not perfect, it wouldn't really be any
different than what .EVEN does.

Johnny
Don North
2022-01-18 00:44:22 UTC
Permalink
Post by Johnny Billquist
Post by Bob Eager
Post by Jonathan Harston
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
.=(.+3)&4
Yeah. Don just got it slightly wrong. :-)
. = (. + 3) & ^C3
(Where ^C means ones complement in Macro-11.)
   . = <. + 3> & ^C3
Of course. I wasn't thinking about getting it MACRO-11 correct. Initially I even
wrote (. + 3) & ~3, but then I figured that maybe using ~ for negation might not
be understood by everyone, so I started MACRO-11:fying it a little. :-)
which as pointed out ONLY works in absolute PSECTs.
Throws an error in relative PSECTs.
Yeah. That is my main issue/problem. I'd like to have one that works in relative
psects. Even though it's not perfect, it wouldn't really be any different than
what .EVEN does.
  Johnny
The problem is the standard PDP-11 linker only guarantees word alignment for
PSECTs. So enforcing a stricter alignment within a PSECT is problematic.
Johnny Billquist
2022-01-18 02:37:09 UTC
Permalink
Post by Don North
Post by Johnny Billquist
Post by Don North
which as pointed out ONLY works in absolute PSECTs.
Throws an error in relative PSECTs.
Yeah. That is my main issue/problem. I'd like to have one that works
in relative psects. Even though it's not perfect, it wouldn't really
be any different than what .EVEN does.
   Johnny
The problem is the standard PDP-11 linker only guarantees word alignment
for PSECTs. So enforcing a stricter alignment within a PSECT is
problematic.
Actually, at least TKB don't even guarantee word alignment. It
guarantees that the first placement of a psect is word aligned, but if
the psect exists in multiple modules, the alignment for the next part of
the psect from the second file isn't even guaranteed to be word aligned.

So be careful if you create a psect with an odd size. That might throw
odd address errors at you from a different module, because you thought
it was word aligned. The .even will actually get you odd addresses...

Johnny
Johnny Billquist
2022-01-17 17:45:28 UTC
Permalink
Post by Jonathan Harston
If your assembler has an 'insert string' directive which takes
DS length,fillbyte
DS (($+3) BINARYAND -4)-$, 0
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
Yes, except that in Macro-11, the location counter in a normal section
is relative, and thus you are not allowed to do an AND on it. :-(

Which in a sense makes sense, since the code you are doing might be
placed on any location by the linker, thus making your computation for
an aligned address at assembler time to not be correct at all.

Johnny
Don North
2022-01-18 00:28:48 UTC
Permalink
Post by Jonathan Harston
If your assembler has an 'insert string' directive which takes
DS length,fillbyte
DS (($+3) BINARYAND -4)-$, 0
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
Yes, except that in Macro-11, the location counter in a normal section is
relative, and thus you are not allowed to do an AND on it. :-(
Which in a sense makes sense, since the code you are doing might be placed on
any location by the linker, thus making your computation for an aligned address
at assembler time to not be correct at all.
  Johnny
If you need to produce guaranteed aligned data structures that are aligned to
more than just a word (16b) boundary in PDP-11, and you need to do it in a
relocatable way, then writing a version of malloc(align,size) is probably your
best bet, and do the data allocation dynamically at run time.

In my recollection PDP-11 long/float quad/double (in relation to FPU in
particular) did not have any alignment requirement, other than word (even).
Johnny Billquist
2022-01-18 02:38:17 UTC
Permalink
Post by Don North
Post by Johnny Billquist
Post by Jonathan Harston
If your assembler has an 'insert string' directive which takes
DS length,fillbyte
DS (($+3) BINARYAND -4)-$, 0
DS (($+num-1) BINARYAND -num)-$,0
where num is a power of two and $ is the location counter.
Yes, except that in Macro-11, the location counter in a normal section
is relative, and thus you are not allowed to do an AND on it. :-(
Which in a sense makes sense, since the code you are doing might be
placed on any location by the linker, thus making your computation for
an aligned address at assembler time to not be correct at all.
   Johnny
If you need to produce guaranteed aligned data structures that are aligned to
more than just a word (16b) boundary in PDP-11, and you need to do it in
a relocatable way, then writing a version of malloc(align,size) is
probably your best bet, and do the data allocation dynamically at run time.
Well, I wish I could do it anyway. Sometimes I want to to strange
things. :-)
Post by Don North
In my recollection PDP-11 long/float quad/double (in relation to FPU in
particular) did not have any alignment requirement, other than word (even).
Correct.

Johnny
Johnny Billquist
2022-01-17 17:43:00 UTC
Permalink
Post by Don North
Post by Johnny Billquist
And while it's pretty straight forward in theory, I can't create such
a padding in MACRO-11. The problem is that I'm not allowed to do that
kind of arithmetic on the current location, as it is a relative value.
But maybe I'm just not creative enough right at this moment.
But with that said, I do have a MACRO-11 definition of .LONG which
works just fine. :-)
   Johnny
FYI I made up this macro for MACRO-11 that aligns the current location counter
such that the 'arg1' low bits are zeroes.
'arg1' can be 1 for word, 2 for longword, 3 for quadword, etc.
HOWEVER the alignment is relative to the start of the current
program/data section, which the linker normally only word aligns. So I
only use it in absolute sections where I can set the starting address to
0, 1000(8), etc.
.macro    align    arg1
.nlist
    $$pos=1
.rept    arg1
.if ne <.&$$pos>
    .blkb    $$pos
.endc
    $$pos=$$pos*2
.endr
.list
.endm    align
The problem with this one, as with all the different attempts I've made
is that you are not allowed to do this in a normal program section.
Basically, <. & n> gives an A error because . is relative.
It only works on absolute sections. :-(

If anyone can come up with a solution that would work on normal
sections, I'd be very interested.

Johnny
Johnny Billquist
2022-01-17 17:37:36 UTC
Permalink
Post by Johnny Billquist
And while it's pretty straight forward in theory, I can't create such
a padding in MACRO-11. The problem is that I'm not allowed to do that
kind of arithmetic on the current location, as it is a relative value.
But maybe I'm just not creative enough right at this moment.
But with that said, I do have a MACRO-11 definition of .LONG which
works just fine. :-)
   Johnny
 Care to share it?
Sure. Here is both .LONG and .QUAD (yes, I occasionally need those on a
PDP-11).

--------snip---------
;
; The .LONG and .QUAD macros are a bit complex since we want to handle
; all different ways of doing radix in MACRO-11.
;
; As such, they understands:
; . Default radix based on .RADIX
; . Explicit ending with . to indicate decimal
; . ^O for octal
; . ^D for decimal
; . ^X for hexadecimal
;
; Note that ^x notation requires the argument to be enclosed
; in <>, since otherwise MACRO-11 tries to parse if before
; the macro expansion happens.
;
; The variables used are:
; $$$F flag if previous char was ^
; $$$B base used for conversion
; $$$B1-$$$B8 the eight bytes accumulating the value
;

;
; $$$TD tests if the argument ends with a dot, and if so
; sets conversion base explicitly to 10.
;
.MACRO $$$TD WORD
.IRPC D,<WORD>
.IF IDN <D> .
$$$B=10.
.ENDC
.ENDR
.ENDM $$$TD

;
; $$$ADD will add one digit, in the appropriate base,
; to the accumulating bytes.
;
.MACRO $$$ADD DI

.IF EQ $$$B-8.
$$$V = ^O'DI
.ENDC
.IF EQ $$$B-10.
$$$V = ^D'DI
.ENDC
.IF EQ $$$B-16.
$$$V = ^X0'DI
.ENDC

.IRPC X,<12345678>

$$$B'X=$$$B'X*$$$B+$$$V
$$$V=$$$B'X/256.
$$$B'X=$$$B'X&^O377

.ENDR

.ENDM $$$ADD

;
; Accumulate a word into multiple bytes.
; The bytes gets into $$$Bn
;
.MACRO $$$ACC WORD
.MCALL $$$TD, $$$ADD

.IRPC X,<12345678>
$$$B'X=0
.ENDR
$$$F=0
$$$B=10

$$$TD <WORD>

.IRPC DI,<WORD>
.IF IDN <DI> <^>
$$$F=1
.IFF
.IF NE $$$F
.IF IDN <DI> O
$$$B=^O10
.ENDC
.IF IDN <DI> D
$$$B=10.
.ENDC
.IF IDN <DI> X
$$$B=^X10
.ENDC
$$$F=0
.IFF
.IF IDN <DI> .
.IFF
$$$ADD <DI>
.ENDC
.ENDC
.ENDC
.ENDR

.ENDM $$$ACC

.MACRO .LONG WORD,ORDER
.MCALL $$$ACC
$$$ACC <WORD>

$$$W1=$$$B2*256.+$$$B1
$$$W2=$$$B4*256.+$$$B3
.LIST MEB
.IF NB ORDER
.WORD $$$W1,$$$W2
.IFF
.WORD $$$W2,$$$W1
.ENDC
.NLIST MEB

.ENDM .LONG

.MACRO .QUAD WORD
.MCALL $$$ACC
$$$ACC <WORD>

$$$W1=$$$B2*256.+$$$B1
$$$W2=$$$B4*256.+$$$B3
$$$W3=$$$B6*256.+$$$B5
$$$W4=$$$B8*256.+$$$B7
.LIST MEB
.WORD $$$W1,$$$W2,$$$W3,$$$W4
.NLIST MEB

.ENDM .QUAD

---------snip---------
Lee Gleason
2022-01-19 02:13:53 UTC
Permalink
Post by Johnny Billquist
Post by Johnny Billquist
And while it's pretty straight forward in theory, I can't create such
a padding in MACRO-11. The problem is that I'm not allowed to do that
kind of arithmetic on the current location, as it is a relative value.
But maybe I'm just not creative enough right at this moment.
But with that said, I do have a MACRO-11 definition of .LONG which
works just fine. :-)
   Johnny
  Care to share it?
Sure. Here is both .LONG and .QUAD (yes, I occasionally need those on a
PDP-11).
--------snip---------
;
; The .LONG and .QUAD macros are a bit complex since we want to handle
; all different ways of doing radix in MACRO-11.
;
; . Default radix based on .RADIX
; . Explicit ending with . to indicate decimal
; . ^O for octal
; . ^D for decimal
; . ^X for hexadecimal
;
; Note that ^x notation requires the argument to be enclosed
; in <>, since otherwise MACRO-11 tries to parse if before
; the macro expansion happens.
;
; $$$F flag if previous char was ^
; $$$B base used for conversion
; $$$B1-$$$B8 the eight bytes accumulating the value
;
;
; $$$TD tests if the argument ends with a dot, and if so
; sets conversion base explicitly to 10.
;
        .MACRO  $$$TD   WORD
        .IRPC   D,<WORD>
        .IF IDN <D> .
        $$$B=10.
        .ENDC
        .ENDR
        .ENDM   $$$TD
;
; $$$ADD will add one digit, in the appropriate base,
; to the accumulating bytes.
;
        .MACRO  $$$ADD  DI
        .IF EQ $$$B-8.
        $$$V = ^O'DI
        .ENDC
        .IF EQ $$$B-10.
        $$$V = ^D'DI
        .ENDC
        .IF EQ $$$B-16.
        $$$V = ^X0'DI
        .ENDC
        .IRPC   X,<12345678>
        $$$B'X=$$$B'X*$$$B+$$$V
        $$$V=$$$B'X/256.
        $$$B'X=$$$B'X&^O377
        .ENDR
        .ENDM   $$$ADD
;
; Accumulate a word into multiple bytes.
; The bytes gets into $$$Bn
;
        .MACRO  $$$ACC  WORD
        .MCALL  $$$TD, $$$ADD
        .IRPC   X,<12345678>
        $$$B'X=0
        .ENDR
        $$$F=0
        $$$B=10
        $$$TD   <WORD>
        .IRPC   DI,<WORD>
        .IF IDN <DI> <^>
        $$$F=1
        .IFF
        .IF NE $$$F
        .IF IDN <DI> O
        $$$B=^O10
        .ENDC
        .IF IDN <DI> D
        $$$B=10.
        .ENDC
        .IF IDN <DI> X
        $$$B=^X10
        .ENDC
        $$$F=0
        .IFF
        .IF IDN <DI> .
        .IFF
        $$$ADD <DI>
        .ENDC
        .ENDC
        .ENDC
        .ENDR
        .ENDM   $$$ACC
        .MACRO  .LONG   WORD,ORDER
        .MCALL  $$$ACC
        $$$ACC  <WORD>
        $$$W1=$$$B2*256.+$$$B1
        $$$W2=$$$B4*256.+$$$B3
        .LIST   MEB
        .IF NB  ORDER
        .WORD   $$$W1,$$$W2
        .IFF
        .WORD   $$$W2,$$$W1
        .ENDC
        .NLIST  MEB
        .ENDM   .LONG
        .MACRO  .QUAD   WORD
        .MCALL  $$$ACC
        $$$ACC  <WORD>
        $$$W1=$$$B2*256.+$$$B1
        $$$W2=$$$B4*256.+$$$B3
        $$$W3=$$$B6*256.+$$$B5
        $$$W4=$$$B8*256.+$$$B7
        .LIST   MEB
        .WORD   $$$W1,$$$W2,$$$W3,$$$W4
        .NLIST  MEB
        .ENDM   .QUAD
---------snip---------
Thanks!

--
Lee K. Gleason N5ZMR
Control-G Consultants
***@comcast.net

Loading...