Discussion:
seg keyword
(too old to reply)
Paul Edwards
2022-11-19 19:22:42 UTC
Permalink
I have code like this:

extrn int0:proc

public handler0

mov bx, 0
push bx
pop es
cli
mov bx, offset handler0
mov es:[0h], bx
mov bx, seg handler0
mov es:[02h], bx


handler0 proc
push bp
push ax


as86 uses 16-bit a.out format, and I'm not sure it can
handle a reference to just "seg". ie half of an address
being fixed up (I think that's what it does).

Is there a better way of writing this code, more in line
with the simple a.out format?

Is it:

addr0 dd handler0

And then do an les of that?

Thanks. Paul.
Alexei A. Frounze
2022-11-19 22:05:14 UTC
Permalink
...
Post by Paul Edwards
mov bx, offset handler0
mov es:[0h], bx
mov bx, seg handler0
mov es:[02h], bx
...
Post by Paul Edwards
as86 uses 16-bit a.out format, and I'm not sure it can
handle a reference to just "seg". ie half of an address
being fixed up (I think that's what it does).
Is there a better way of writing this code, more in line
with the simple a.out format?
addr0 dd handler0
And then do an les of that?
I don't recall the a.out format supporting segmentation.

I found my way around the similar problem with the ELF
format by simply using 32-bit physical addresses,
which are then decomposed into 16-bit segment and
16-bit offset pairs whenever necessary.

Alex
Paul Edwards
2022-11-20 01:01:40 UTC
Permalink
Post by Alexei A. Frounze
Post by Paul Edwards
addr0 dd handler0
And then do an les of that?
I don't recall the a.out format supporting segmentation.
I found my way around the similar problem with the ELF
format by simply using 32-bit physical addresses,
which are then decomposed into 16-bit segment and
16-bit offset pairs whenever necessary.
How do I use a 32-bit physical address?

Is it like above?

Thanks. Paul.
Alexei A. Frounze
2022-11-20 04:03:20 UTC
Permalink
Post by Paul Edwards
Post by Alexei A. Frounze
Post by Paul Edwards
addr0 dd handler0
And then do an les of that?
I don't recall the a.out format supporting segmentation.
I found my way around the similar problem with the ELF
format by simply using 32-bit physical addresses,
which are then decomposed into 16-bit segment and
16-bit offset pairs whenever necessary.
How do I use a 32-bit physical address?
Is it like above?
Yes.

I used the assembler (NASM) in the 32-bit non-segmented mode,
where all addresses are simply 32-bit offsets.

The linker, startup code (AKA loader) and generated code then
convert these into seg16:ofs16 using 80386 32-bit instructions.

[This is SmallerC's huge memory model in a nutshell.]

While said conversion is conceptually trivial, only a few 8086
instructions (far call, far jump, lds/les) can consume 32 bits
of an address (seg16:ofs16). Everywhere else you have the far
address split into two 16-bit portions with some space (code)
between the two.

If you want to be able to use these 16-bit parts independently,
you need to produce two special kinds of relocation records,
one for the SEG keyword, the other for the OFS/OFFSET.
The latter is more or less trivial and already exists, but is
probably 32-bit in your assembler, whereas it needs to be 16-bit.
The former needs to be introduced.

The simplest is perhaps to restrict every object file to
two segments/sections (code and data), each at most 64KB
in size and 16-byte aligned and padded to a multiple of 16 bytes.
OFS/OFFSET would then be the subroutine/variable offset
from the beginning of its segment/section in the object file.
SEG would simply account for the cumulative size of all
the linked object files. In essence, you end up relocating
only the SEG part as the OFS/OFFSET part is fixed.

Otherwise you could dump all far pointers into the default
data segment and simply do lds/les as needed (naturally,
the pointer values must've been relocated by then).

Alex
Paul Edwards
2022-11-20 12:23:09 UTC
Permalink
Post by Paul Edwards
How do I use a 32-bit physical address?
Is it like above?
Yes.
Thanks. I just went ahead and tried that, but it didn't seem to work.

Any idea what I did wrong?

Here is the old (working) code:

; Released to the public domain by Matthew Parker on 4 December 1995
; Mods by Paul Edwards, also public domain.
; For different models just change the .model directive

% .model memodel, c

public instint

extrn int0:proc
extrn int1:proc
extrn int3:proc
extrn int20:proc
extrn int21:proc
extrn int25:proc
extrn int26:proc

public handler0
public handler1
public handler3
public handler20
public handler21
public handler25
public handler26

.code

instint proc uses bx es
mov bx, 0
push bx
pop es
cli
mov bx, offset handler0
mov es:[0h], bx
mov bx, seg handler0
mov es:[02h], bx
mov bx, offset handler1
mov es:[04h], bx
mov bx, seg handler1
mov es:[06h], bx
mov bx, offset handler3
mov es:[0ch], bx
mov bx, seg handler3
mov es:[0eh], bx
mov bx, offset handler20
mov es:[80h], bx
mov bx, seg handler20
mov es:[82h], bx
mov bx, offset handler21
mov es:[84h], bx
mov bx, seg handler21
mov es:[86h], bx
mov bx, offset handler25
mov es:[94h], bx
mov bx, seg handler25
mov es:[96h], bx
mov bx, offset handler26
mov es:[98h], bx
mov bx, seg handler26
mov es:[9Ah], bx
sti
ret
instint endp

; the stack will already have
; flags
; cs
; ip

handler0 proc
push bp
push ax
push ax ; dummy, actually cflag storage
push bx
push cx
push dx
push si
push di
push ds
push es

mov dx, DGROUP
mov ds, dx
mov ax, sp
push ss
push ax
call int0
add sp, 4

pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax ; actually cflag

cmp ax, 0
je clear0
jmp notclear0
clear0:
pop ax
push bp
mov bp, sp
and word ptr [bp+6],0fffeh
pop bp
pop bp
iret
notclear0:
pop ax
push bp
mov bp, sp
or word ptr [bp+6],0001h
pop bp
pop bp
iret
handler0 endp

...

And here is the new code, which is now preventing PDOS/86
from booting:

; Released to the public domain by Matthew Parker on 4 December 1995
; Mods by Paul Edwards, also public domain.
; For different models just change the .model directive

% .model memodel, c

public instint

extrn int0:proc
extrn int1:proc
extrn int3:proc
extrn int20:proc
extrn int21:proc
extrn int25:proc
extrn int26:proc

public handler0
public handler1
public handler3
public handler20
public handler21
public handler25
public handler26

.data
addr0 dd handler0
addr1 dd handler1
addr3 dd handler3
addr20 dd handler20
addr21 dd handler21
addr25 dd handler25
addr26 dd handler26

.code

instint proc uses bx es ds
mov bx, 0
push bx
pop es
cli

lds bx, addr0
mov es:[0h], bx
mov es:[02h], ds

lds bx, addr1
mov es:[04h], bx
mov es:[06h], ds

lds bx, addr3
mov es:[0ch], bx
mov es:[0eh], ds

lds bx, addr20
mov es:[80h], bx
mov es:[82h], ds

lds bx, addr21
mov es:[84h], bx
mov es:[86h], ds

lds bx, addr25
mov es:[94h], bx
mov es:[96h], ds

lds bx, addr26
mov es:[98h], bx
mov es:[9Ah], ds

sti
ret
instint endp

; the stack will already have
; flags
; cs
; ip

handler0 proc
push bp
push ax
push ax ; dummy, actually cflag storage

...



Thanks. Paul.
Paul Edwards
2022-11-23 02:14:07 UTC
Permalink
Post by Paul Edwards
And here is the new code, which is now preventing PDOS/86
I decided to have another crack at this, to see if the
recent changes to pdos/86 to build it using the huge
memory model instead of the large memory model,
with a 32-bit size_t, but still pure 8086 code, had made
this problem go away. But the problem was still there.
Post by Paul Edwards
.data
addr0 dd handler0
addr1 dd handler1
addr3 dd handler3
addr20 dd handler20
addr21 dd handler21
addr25 dd handler25
addr26 dd handler26
.code
instint proc uses bx es ds
mov bx, 0
push bx
pop es
cli
lds bx, addr0
This causes ds to be destroyed.
Post by Paul Edwards
mov es:[0h], bx
mov es:[02h], ds
lds bx, addr1
This uses the destroyed ds to attempt to access addr1 :-)

I solved the problem by doing this:

push ds
lds bx, addr1
mov es:[04h], bx
mov es:[06h], ds
pop ds

And now all of wasm, masm and as86 assemble the code,
but I can only test that wasm and masm actually work.

BFN. Paul.
Kerr-Mudd, John
2022-11-23 12:56:44 UTC
Permalink
On Tue, 22 Nov 2022 18:14:07 -0800 (PST)
Post by Paul Edwards
Post by Paul Edwards
And here is the new code, which is now preventing PDOS/86
I decided to have another crack at this, to see if the
recent changes to pdos/86 to build it using the huge
memory model instead of the large memory model,
with a 32-bit size_t, but still pure 8086 code, had made
this problem go away. But the problem was still there.
Post by Paul Edwards
.data
addr0 dd handler0
addr1 dd handler1
addr3 dd handler3
addr20 dd handler20
addr21 dd handler21
addr25 dd handler25
addr26 dd handler26
.code
instint proc uses bx es ds
mov bx, 0
push bx
pop es
cli
lds bx, addr0
This causes ds to be destroyed.
^w overwritten
Post by Paul Edwards
Post by Paul Edwards
mov es:[0h], bx
mov es:[02h], ds
lds bx, addr1
This uses the destroyed ds to attempt to access addr1 :-)
push ds
lds bx, addr1
mov es:[04h], bx
mov es:[06h], ds
pop ds
You've changed the target address?!

If all your doing is moving some dwords, 'movsd' might be what you need.
Post by Paul Edwards
And now all of wasm, masm and as86 assemble the code,
but I can only test that wasm and masm actually work.
BFN. Paul.
--
Bah, and indeed Humbug.
Paul Edwards
2022-11-23 20:00:24 UTC
Permalink
Post by Kerr-Mudd, John
Post by Paul Edwards
push ds
lds bx, addr1
mov es:[04h], bx
mov es:[06h], ds
pop ds
You've changed the target address?!
Sorry, I don't understand.
Post by Kerr-Mudd, John
If all your doing is moving some dwords, 'movsd' might be what you need.
Thanks, let me look into that.

By the way, I realized something.

Isn't "mov ax, DGROUP"

effectively a move of a segment?

If a.out can handle passing on the DGROUP reference, why
not the segment of other references?

Or will that be specially known by the linker?

Thanks. Paul.
Paul Edwards
2022-11-24 01:15:32 UTC
Permalink
Post by Kerr-Mudd, John
If all your doing is moving some dwords, 'movsd' might be what you need.
I think that is an 80386 instruction based on the error
I got from Watcom. I am after 8086.

movsw is available, but it didn't seem to buy anything
more than I already had.

BFN. Paul.
Kerr-Mudd, John
2022-11-24 16:54:08 UTC
Permalink
On Wed, 23 Nov 2022 17:15:32 -0800 (PST)
Post by Paul Edwards
Post by Kerr-Mudd, John
If all your doing is moving some dwords, 'movsd' might be what you need.
I think that is an 80386 instruction based on the error
I got from Watcom. I am after 8086.
movsw is available, but it didn't seem to buy anything
more than I already had.
Fine. but it would avoid loading seg registers unneccessarrilly (delete
duplicate letters to suit).
--
Bah, and indeed Humbug.
Paul Edwards
2022-11-24 20:36:16 UTC
Permalink
Post by Kerr-Mudd, John
Post by Paul Edwards
movsw is available, but it didn't seem to buy anything
more than I already had.
Fine. but it would avoid loading seg registers unneccessarrilly (delete
duplicate letters to suit).
Is that for performance reasons?

Thanks. Paul.
Kerr-Mudd, John
2022-11-25 12:23:49 UTC
Permalink
On Thu, 24 Nov 2022 12:36:16 -0800 (PST)
Post by Paul Edwards
Post by Kerr-Mudd, John
Post by Paul Edwards
movsw is available, but it didn't seem to buy anything
more than I already had.
Fine. but it would avoid loading seg registers unneccessarrilly (delete
duplicate letters to suit).
Is that for performance reasons?
Thanks. Paul.
No, it just avoids Pushing & Popping ds; your choice.
--
Bah, and indeed Humbug.
Loading...