The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: kweekvijver on September 24, 2006, 08:35:40 AM

Title: fill struct member
Post by: kweekvijver on September 24, 2006, 08:35:40 AM
I'm trying to fill in a WAVEHDR structure, but the compiler keeps complaining about error A2070: invalid instruction operands


.data?
m_WaveHeader   WAVEHDR     <>
m_Data         db 1024 dup (?)

.code
mov     m_WaveHeader.lpData,            m_Data     ; error A2070
;mov     m_WaveHeader.lpData,            [m_Data]   ; just to test if this works


Trying to load the address of m_Data into a register first and then place this address
into lpData didn't solve it either.


I cannot figure out whats wrong here. Can abybody point me in the right direction?
Title: Re: fill struct member
Post by: ic2 on September 24, 2006, 09:19:52 AM
Just Looking at your code and comparing to something i use

.data?
m_WaveHeader   WAVEHDR     <>
m_Data         db 1024 dup (?)

Should the m_Data be an equ like MAX_PATH
below or under .data and not .data? because
you are dealing with byte data

and should

m_WaveHeader   WAVEHDR     <>

be

m_WaveHeader   WAVEHDR     <?>

under .data? as you have it

###########################

.const

MAX_PATH                             equ 260


FIND_DATA STRUCT
  dwFileAttributes DWORD    ?
  ftCreationTime FILETIME <>
  ftLastAccessTime FILETIME <>
  ftLastWriteTime FILETIME <>
  nFileSizeHigh DWORD    ?
  nFileSizeLow DWORD    ?
  dwReserved0 DWORD    ?
  dwReserved1 DWORD    ?
  cFileName BYTE MAX_PATH dup(?)
  cAlternate BYTE 14 dup(?)
FIND_DATA ENDS


If you get something out of this great if not i give you a full example.
Title: Re: fill struct member
Post by: ic2 on September 24, 2006, 09:33:21 AM
Also should you be moving the data into a register or something

mov m_WaveHeader.lpData

should be

mov eax, m_WaveHeader.lpData

Title: Re: fill struct member
Post by: zooba on September 24, 2006, 09:48:11 AM
What you appear to be trying to do is put the address of m_Data into the lpData member of m_WaveHeader. To do this, you'll either need to use the OFFSET operator or the LEA instruction:

lea eax, m_Data
mov m_WaveHeader.lpData, eax


or

mov m_WaveHeader.lpData, OFFSET m_Data

The advantage of the first one is that it will work on local variables as well as global ones. The disadvantage is that it requires an extra instruction and a register. This is the code that gets assembled when you use the 'ADDR' operator in INVOKE statements (which is why you can't use ADDR and EAX in the same statement :wink )

The second one will only work for variables defined in a segments (as yours are) and not as LOCALs, ie. the assembler needs to be able to determine the address at compile time which it can't for variables stored on the stack. On the plus side, it assembles to an immediate, so you can move it straight into a memory location (ie. you don't need to go via a register).

To answer ic2's query, the difference between .data and .data? is that the first one is initialised and stored in the executable, so defining a 1024 byte array in the .data section will add 1024 bytes to the .exe file, while the second is allocated when the process starts, so defining large arrays here don't increase the size of the executable. However, the initial values of variables in the .data? section are not defined and should be initialised at run time. IIRC, structures defined with the <> notation don't require a question mark, but it's easy enough to fix if it doesn't compile :wink

Cheers,

Zooba :U
Title: Re: fill struct member
Post by: PBrennick on September 24, 2006, 09:49:44 AM
mov     eax, m_Data
mov     m_WaveHeader.lpData, eax

Paul
Title: Re: fill struct member
Post by: kweekvijver on September 24, 2006, 10:13:26 AM
The code as specified by Zooba worked  :cheekygreen:.
I have tried something similar before, but can't remember exactly what, I've must have done something wrong here.