News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

ML (6.1 or later) syntax question

Started by filofel, December 08, 2005, 08:17:42 AM

Previous topic - Next topic

filofel

Hi,

Does anyone around know if there is a syntax that ML would accept to generate a direct MOV from / to a paragraph-aligned structure mapped through a seg reg, WITHOUT having to declare an actual segment?
An example would probably help here:

What I would like to achieve is described in the following, non compiling pseudo-ML:
Foo STRUCT
  Member1 WORD
  Member2 WORD
Foo ENDS

  CALL GetFooStrucPara       ; Returns or allocate a paragraph (seg) address containing the struct.
  MOV DS,AX

  ASSUME DS:PTR Foo         ; <- Doesn't compile for a seg reg

  MOV AX,Member2             ; Doesn't compile either, Member2 unknown(sure, since ASSUME didn't compile)


This is 100% non functional code, but I hope you see the idea:
Indicating ML that DS:0 is the origin of that structure, so it generates direct seg relative addressing for each struct member.

I made a number of desesperate and pathetic attemps at various (and unprobable) combinations such as
  MOV AX, Foo PTR [0].Member2
  MOV AX, Foo PTR DS:[0].Member2
  MOV AX, DS:Foo.Member2
 
  ...
  to no avail.

I know I could of course kludge around like in
  ASSUME BX:PTR Foo         ; <- Does compile

  XOR BX,BX
  MOV AX,[BX].Member2       ; Does compile cuz ML now knows BX => Foo.


but that needlessly wastes a base register.

I can also create a dummy segment AT <something> and pretend ASSUMEing it (that does work), but that's really cumbersome when the number of different structures that can be handled this way increases.
There has to be a better, smarter looking, more readable [, obvious ::) ?] way that I haven't found so far.

Any clue anyone?

Thanks in advance! /Ph.

MichaelW


.model small
.386
.stack
BASE_IO_ADDR STRUCT
  serial_port1 WORD ?
  serial_port2 WORD ?
  serial_port3 WORD ?
  serial_port4 WORD ? 
BASE_IO_ADDR ENDS
.data
  dummy BASE_IO_ADDR <>
.code
.startup
    ; Load ES with the segment address of the BIOS data.
    mov ax,40h
    mov es,ax   
    ; Using a dummy variable at offset 0 in the data segment.
    mov ax,es:dummy.serial_port1
    mov dx,es:dummy.serial_port2
    ; Using the structure as a template.
    mov bx,0
    mov ax,es:[bx+BASE_IO_ADDR.serial_port1]
    mov dx,es:[bx+BASE_IO_ADDR.serial_port2]
    mov ah,0
    int 16h
.exit
end


hth
eschew obfuscation

filofel

Michael,

Thanks for your answer. That's very close to what I meant when I said
"I create a dummy segment AT <something> and pretend ASSUMEing it (that does work)".
The difference with your code is marginal, I'm using a SEGMENT AT as a template, and it defines the seg address at the same time:

BiosData SEGMENT AT 040h
  MyBaseIOAddr BASE_IO_ADDR <>

    ORG 012h
  MemSize DWORD ?                       

BiosData ENDS


  MOV AX, BiosData
  MOV ES,AX

  ASSUME DS:NOTHING, ES:BIOSData

  ; Not syntax error because MyBaseIO is know as a BASE_IO_ADDR struct, and ES is known to the segment that
  ; gives access to said varialble.

  MOV AX, MyBaseIOAddr.serial_port1  ; Will even generate the ES: prefix automatically
                                     ; since that's the only path to the Dummy seg.


The AT definition doesn't reserve any space nor generate any static data (which I don't need, since I'm only looking for a data template that will generate the right addressing bits and bytes. Additionnally, because the BiosData is at a fixed address, it provides a one stop clear and consistent description of what the data is and the code does.

But in my case, the structure is floating around, as it is dynamically allocated on a paragraph. And when there are many different possible paragraph-aligned structures like that, defining a dummy seg with a dummy instance for each type of structure is a plain kludge, requires defining for each struct type a yet another segment name and yet another variable name in addition to the structure itself, and in the end, obscures the code rather than making it clear.

That's why I'm looking for an alternate, lighter, more directly understandable way.
I would be surprised if there weren't, but it could be the case, though.
ML syntax has many little known / little documented capabilities and the documentation (the MASM 6 programmer's guide) is not that helpful in complex situations.

Hmmm... Still searching... /Ph.

filofel

Ah ah!

Looks like I found a way after all.
That's a kludge, still, but it's lighter, more universal and with a careful choice of symbol names, can be made more readable, too.
               
0000            ThisSeg SEGMENT AT 0
0000 = 0000          SegOrigin EQU $
0000            ThisSeg ENDS

0004            AStruct STRUCT
0000  0000          Foo1 WORD ?
0002  0000          Foo2 WORD ?
            AStruct EndS

0004            AnotherStruct STRUCT
0000  0000          Bar1 WORD ?
0002  0000          Bar2 WORD ?
            AnotherStruct EndS

                          (...)
            ASSUME DS:ThisSeg
                          (...)       
0000  A1 0000 R    MOV AX,(AStruct PTR SegOrigin).Foo1
              (...)
0003  A1 0002 R    MOV AX,(AnotherStruct PTR SegOrigin).Bar2
                          (...)
            ASSUME DS:NOTHING
                          (...)


For the record, I also discovered while seeking a solution that
0006  B8 0000              MOV AX,AStruct.Foo1
assembles quietly and silently with no warning just as
0009  B8 0000              MOV AX,OFFSET AStruct.Foo1
Looks a bit dangerous to me.

It sure would be better if ML accepted that a segregister can be ASSUMEd to a qualifiedtype (e.g. AStruct PTR) like a dataregister can, e.g. if
  ASSUME DS:AStruct PTR
was just as legal as
  ASSUME BX:AStruct PTR

Or if ML accepted a specific conventional "I-do-mean-this" syntax such as
  MOV AX, (PTR AStruct[0]).Foo2
just as it takes
  MOV AX, (PTR AStruct[BX]).Foo2

But at least, the above kludge solves the problem and only requires a small and fixed source code overhead, whatever the number of distinct struct types that can be accessed this way. /Ph.

filofel

No more dummy segment or other kludge, I finally ran into the suitable syntax.

  MOV AX,(AStruct PTR DS:[0]).Foo1

Now *that's* what I was looking for.
I was pretty close in the latest iteration.
In fact, I was missing the parentheses in my previous (unsuccessful) tries. /Ph.