News:

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

Using a template

Started by Robert Collins, February 15, 2005, 04:25:49 AM

Previous topic - Next topic

Robert Collins

How do you go about mapping a data format template on top of the actual data string MASM32?

When I was doing BAL there was an assemble declarative called a DSECT which meant Dummy Section. It was nothing more than a non-assemable layout of a file's format. The data was read into a data buffer 'InputDataBuffer'. Then. in the code you would do this:


DSECT   CUST_RECORD
Name    DS 
Address DS
  '
  '
END
  '
  '
LA R5,InputDataBuffer                          Use register 5 and point to where data is
USING CUST_RECORD,R5                           Tell assembler to use register 5 in below code
  '
mvc save_name,Name                             Name is an offset from the address in reg 5
mvc save_addr,Address
  '
  ' 


So is there a way to do this in MASM32?

Relvinian

Robert,

Thiink of what you shown as a structure. Once you have your structure defined (on what your data represents), then you can just access it like you have shown.

An example:

.const
   MyTemplateFormat STRUCT
        Name         byte 64  dup (?)
        Address      byte 128 dup (?)
        City            byte 32  dup (?)
        State         byte  10 dup (?)
        Zip             byte 12 dup (?)
   MyTemplateFormat ENDS

.code
MyFunction proc uses ebx lpName:dword, lpAddress:dword, lpCity:dword, lpState:dword, lpZip:dword
   UserRec : MyTemplateFormat <>

   ; load the structure address into EBX to copy data into
   lea ebx, UserRec

   ; copy the parameters into our structure to work with
   invoke lstrcpy, [ebx].MyTemplateFormat.Name, lpName
   invoke lstrcpy, [ebx].MyTemplateFormat.Address, lpAddress
   invoke lstrcpy, [ebx].MyTemplateFormat.City, lpCity
   invoke lstrcpy, [ebx].MyTemplateFormat.State, lpState
   invoke lstrcpy, [ebx].MyTemplateFormat.Zip, lpZip

   ; now you have a structure (can be called a template) of data.

   ; alternatively, you can read from a file and fill in this structure too.
MyFunction endp


Hope this helps you get going.

Relvinian

Robert Collins

Relvinian,

Thanks for your response. Your example is basically what I was doing (in VB, but your assembly coded version was what I needed to get started). What I was trying to do is to somehow 'mimic' the BAL method.

In the BAL example one could also do this............


DSECT   CUST_RECORD                            Define the data layout (DSECT doesnt really exists).
Name    DS                                     This is just a map of the file format so that the
Address DS                                     Assembler can calculate addresses to the actual
  '                                            data in the input data buffer
  '
END
  '
  '
LA R5,InputDataBuffer1                         Use register 5 and point to where 1st record is
USING CUST_RECORD,R5                           Tell assembler to use register 5 in below code
  '
mvc save_name,Name                             Name is an offset from the address in reg 5
mvc save_addr,Address
  '
  ' 
LA R6,InputDataBuffer2                         Use register 6 and point to where 2nd record is
USING CUST_RECORD,R6                           Tell assembler to use register 6 in below code
  '
mvc save_name,Name                             Name is an offset from the address in reg 6
mvc save_addr,Address
  '
  ' 


As you can see I am able to 'map' two completely different data buffers with the same template. 'Name' in the first set of code is an offset from the address in R5 while 'Name' in the second set of code is an offset from the address in R6. The data is always in the buffers and never 'moved' into a structure.

This is what I was wanting to do. Be able to process the data directly from the buffer by mapping it's fields so I can either write to or read from the buffers using the names of the fields and not having to 'move' buffer to a pre-built structure.   

The addresses were created at compile time rather than at run time. Since the addresses are compile time generated you can at will simply switch registers with alternate addresses in them and basically call the same function passing the new address. With this type of functionality you can see the power of using templates in BAL. So, why not in assembly? Your example may be the only way to get close to what I am trying to do and with some modifications make it a generic function.

The first problem I see is that in assembly you would need a structure for each data buffer. But I will work on it starting with your example, so again, thanks for the snippit.


BTW:

Is there any to to move and receive data into/out of a structure as one entire piece of data rather than each field at a time? Maybe what you say about reading from a file and filling in this structure.    

Relvinian

Robert,

Defining a structure is the best way to "organize data".  That's what a template is -- is just organized data is some fashion.

To read and write a whole structure at a time to like a file, all you need to know is the starting address and the length then read/write the data.

To have multiple "buffers" with using the same structure, here's another example:


MyProc proc param1:MyStruct, param2:MyStruct
    ; both parameters are the same structure but have different contents. To access individual
    ; members, we need to tell MASM how to reference it. There are many ways but I'll only
    ; list two of them.


; FIRST WAY
;============
    ; get our params into ECX and EDX
    mov ecx, param1
    mov edx, param2

    ; define how ECX and EDX registers are referenced
    assume ecx:MyStruct
    assume edx:MyStruct

    ; now access a member of MyStruct (checking to see if strings are 'empty' or not)
    cmp byte ptr [ecx].FirstName, 0     ; FirstName field on param1
    cmp byte ptr [edx].LastName, 0     ; LastName field on param2


; SECOND WAY
;==============
    ; get our params into ECX and EDX
    mov ecx, param1
    mov edx, param2

    ; now access a member of MyStruct (checking to see if strings are 'empty' or not)
    cmp byte ptr [ecx].MyStruct.FirstName, 0     ; FirstName field on param1
    cmp byte ptr [edx].MyStruct.LastName, 0     ; LastName field on param2
MyProc endp


The code you have listed is basically doing the same thing. Just reference the way you use a register and how to "map" it to the known structure.

Relvinian

tenkey

For the move instructions:

MVCL --> REP MOVSB ; uses regs only: ESI (source), EDI (destination), and ECX (count)
There is no one-instruction equivalent for MVC. There might be a memmove subroutine in the MASM32 library.
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8


Robert Collins


If I remember correctly MVC A,B could move up to 256 bytes and MVCL could move up 32765 bytes. If REP MOVSB is an equivalent for MVCL then it seems that it would also be the equivalent for the MVC instruction as well. 

tenkey

It's not, because you must always set the length in another instruction.

The equivalent of MVC A(128),B takes four instructions:
lea edi,A
lea esi,B
mov ecx,128
rep movsb
; EDI and ESI will point to the bytes after A and B
; ECX = 0


And this is only true if everyone has been following the Windows API convention of preserving DF (all APIs expect the Direction [Descending] Flag to be cleared on entry and exit).

If the first bytes of data are aligned on DWORD boundaries, and the length is a multiple of 4, you can speed the copy by dividing the count in ECX by 4 and replacing MOVSB with MOVSD.
lea edi,A
lea esi,B
mov ecx,32 ; number of DWORDs
rep movsd  ; use DWORD version
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8