News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Operands must be same size

Started by riversr54, October 13, 2018, 09:09:37 AM

Previous topic - Next topic

riversr54

I'm still learning Assembly and admit that I have a lot to learn. Apparently this is one of those things.

I'm trying to pass the address of a BYTE array to a procedure and then use that address with an offset to insert a byte of data into the array. I've tried everything I can think of but I can't seem to get past the "Operands but be the same size" error.

The array declaration:
     movesArray BYTE 9 DUP(0FFh)

The procedure PROTO:
     RecordMove PROTO, ptrArray:PTR DWORD

The procedure call:
     INVOKE RecordMove, ADDR movesArray

The Procedure code:
     RecordMove PROC, ptrArray:PTR DWORD
     pushad
     mov al, 1
     mov esi, 0
     mov ptrArray[esi], al
     popad
     ret
     RecordMove ENDP


The "mov ptrArray[esi], al' instruction is where I encounter the error. I thought I understood that since the array is an array of bytes, that I could mov a byte of data directly into any location (offset by ESI).

What am I missing? I would really appreciate any help.

riversr54

riversr54

I just realized that I had the ptrArray variable declared as:

ptrArray:PTR DWORD

when I made my post. I've changed them to

ptrArray:PTR BYTE

but still have the same problem.


RuiLoureiro

Quote from: riversr54 on October 13, 2018, 09:09:37 AM
I'm still learning Assembly and admit that I have a lot to learn. Apparently this is one of those things.

I'm trying to pass the address of a BYTE array to a procedure and then use that address with an offset to insert a byte of data into the array. I've tried everything I can think of but I can't seem to get past the "Operands but be the same size" error.

The array declaration:
     movesArray BYTE 9 DUP(0FFh)

The procedure PROTO:
     RecordMove PROTO   :DWORD    ; any pointer is a dword

The procedure call:
     INVOKE RecordMove, ADDR movesArray

The Procedure code:
     RecordMove PROC   ptrArray:DWORD     ; any pointer is a dword
     pushad
     mov al, 1
    mov esi,
ptrArray    ; set the address to esi
     mov [esi], al          ; the same as:  mov byte ptr [esi], al
     popad
     ret
     RecordMove ENDP


The "mov ptrArray[esi], al' instruction is where I encounter the error. I thought I understood that since the array is an array of bytes, that I could mov a byte of data directly into any location (offset by ESI).

What am I missing? I would really appreciate any help.

riversr54

hutch--

The usual notation is "BYTE PTR" or "DWORD PTR" which will always be the native size of the OS version, DWORD in Win32, and the data size it points to which may be anything from BYTE data to DWORD in Win32.

The rough distinction is between an ADDRESS and what is AT that address. The ADDRESS will always be an OFFSET within the memory address space of the current process and the content can be whatever is written at that address. It can be numeric or it can point to an array of characters, what is normally called a "string".

hutch--

See if this is of any use to you, a simple test piece.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    .data
      pArray BYTE 128 dup (0)    ; zero filled BYTE array
      gArray DWORD pArray        ; get the pointer to pArray

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL parr :DWORD

    lea eax, pArray
    mov parr, eax

    print "LOCAL  pointer = "
    print str$(parr),13,10,13,10

    print "GLOBAL pointer = "
    print str$(gArray),13,10,13,10

    mov eax, parr

    mov BYTE PTR [eax],   "T"
    mov BYTE PTR [eax+1], "h"
    mov BYTE PTR [eax+2], "i"
    mov BYTE PTR [eax+3], "s"

    mov BYTE PTR [eax+4], " "
   
    mov BYTE PTR [eax+5], "i"
    mov BYTE PTR [eax+6], "s"

    mov BYTE PTR [eax+7], " "
   
    mov BYTE PTR [eax+8], "a"

    mov BYTE PTR [eax+9], " "

    mov BYTE PTR [eax+10], "t"
    mov BYTE PTR [eax+11], "e"
    mov BYTE PTR [eax+12], "s"
    mov BYTE PTR [eax+13], "t"

    mov BYTE PTR [eax+14], 0

    print parr,13,10,13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start


riversr54

I left a little detail out of my first post to simplify things, which was a mistake. I changed the PTR variables to DWORD as per RuiLoureiro's post.

Procedure declaration:
RecordMove PROTO, ptrArray:PTR DWORD, cellChoice:BYTE, player:BYTE

Procedure call:
INVOKE RecordMove, ADDR movesArray, cellChoice, player

Procedure definition:

RecordMove PROC, ptrArray:PTR DWORD, cellChoice : BYTE, player : BYTE
   pushad
   movzx esi, cellChoice         ; offset into array
   sub esi, 31h                      ; convert from ascii code to array offset
   mov al, player
   mov ptrArray[esi], al
   popad
   ret
   RecordMove ENDP


The idea here is that I use cellChoice as an offset into the array and then store player in that location. I suspect that I am using ESI incorrectly but I've used it like this in other code with no problems. Any other suggestions, corrections would be greatly appreciated.



RuiLoureiro

Quote from: riversr54 on October 14, 2018, 09:08:45 AM
I left a little detail out of my first post to simplify things, which was a mistake. I changed the PTR variables to DWORD as per RuiLoureiro's post.

;---------------------------------------------------------------------
; Why you use ',' ? it does nothing. PTR does nothing also
; Are you using MASM ?
;----------------------------------------------------------------------
Procedure declaration:
RecordMove PROTO, ptrArray:PTR DWORD, cellChoice:BYTE, player:BYTE
                       here above

Procedure call:
INVOKE RecordMove, ADDR movesArray, cellChoice, player  ; this is ok !

Procedure definition:

;-----------------------------------------------------------------------------------
; 1. cellChoice may be DWORD also, no problems and is better.
; 2. If it is an offset it must be 0 or 1, or, 2, or 3, or ... N. Nothing more
; 3. mov   esi, ptrArray
;     add    esi, cellChoice
;     mov   [esi], al              ; move player to array, offset 0 or 1 or 2 or 3, etc
;-----------------------------------------------------------------------------------
RecordMove PROC, ptrArray:PTR DWORD, cellChoice : BYTE, player : BYTE
                      here above

   pushad     ; replace by push  esi only

   ;-----------------------------------------------------
   ; This in RED doesnt do what you want to do.
  ;-------------------------------------------------------
   
movzx esi, cellChoice         ; offset into array
   sub esi, 31h                      ; convert from ascii code to array offset

   mov al, player
   mov ptrArray[esi], al
   popad                         ; replace by pop esi only Do you need to save EAX ?
   ret
   RecordMove ENDP


The idea here is that I use cellChoice as an offset into the array and then store player in that location. I suspect that I am using ESI incorrectly but I've used it like this in other code with no problems. Any other suggestions, corrections would be greatly appreciated.
:t

jj2007

Does this build without errors on your machine?
RecordMove PROC, ptrArray:PTR DWORD, cellChoice : BYTE, player : BYTE
   pushad
   movzx esi, cellChoice         ; offset into array
   sub esi, 31h                      ; convert from ascii code to array offset
   mov al, player
   mov ptrArray[esi], al
   popad
   ret
   RecordMove ENDP


You should
- always post complete code; the reason is that those who are willing to help you will wish to build your source and then test it in action (and they have no spare time to write headers and footers and .data around your snippets)
- never, ever post code that doesn't build properly, except if accompanied by the error messages.

RuiLoureiro

#8
reversr54,
                Take a look at this message:

Quote from: jj2007 on October 14, 2018, 12:14:19 PM
Does this build without errors on your machine?
RecordMove PROC, ptrArray:PTR DWORD, cellChoice : BYTE, player : BYTE
   pushad
   movzx esi, cellChoice         ; offset into array
   sub esi, 31h                      ; convert from ascii code to array offset
   mov al, player
   mov ptrArray[esi], al
   popad
   ret
   RecordMove ENDP


You should
- always post complete code; the reason is that those who are willing to help you will wish to build your source and then test it in action (and they have no spare time to write headers and footers and .data around your snippets)
- never, ever post code that doesn't build properly, except if accompanied by the error messages.
Quote
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
include \masm32\include\masm32rt.inc
.686P
.mmx
.xmm
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
                RecordMove          PROTO     ptrArray:DWORD, cellChoice:DWORD, player:BYTE 
                RecordMove_v2     PROTO     ptrArray:DWORD, cellChoice:BYTE,     player:BYTE
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
movesArray db 9 DUP(0)
                   db 0
           
kcellChoice  dd 0
kplayer       db 'a'

.code
;==========================================================
start:

            INVOKE RecordMove, ADDR movesArray, 0, 'a'
            INVOKE RecordMove, ADDR movesArray, 1, 'b'
            INVOKE RecordMove, ADDR movesArray, 2, 'c'
            INVOKE RecordMove, ADDR movesArray, 3, 'd'
            INVOKE RecordMove, ADDR movesArray, 4, 'e'
            INVOKE RecordMove, ADDR movesArray, 5, 'f'
            INVOKE RecordMove, ADDR movesArray, 6, 'g'
            INVOKE RecordMove, ADDR movesArray, 7, 'h'
            INVOKE RecordMove, ADDR movesArray, 8, 'i'

            print   addr movesArray, 13, 10

            INVOKE RecordMove_v2, ADDR movesArray, '1', 'A'
            INVOKE RecordMove_v2, ADDR movesArray, '2', 'B'
            INVOKE RecordMove_v2, ADDR movesArray, '3', 'C'
            INVOKE RecordMove_v2, ADDR movesArray, '4', 'D'
            INVOKE RecordMove_v2, ADDR movesArray, '5', 'E'
            INVOKE RecordMove_v2, ADDR movesArray, '6', 'F'
            INVOKE RecordMove_v2, ADDR movesArray, '7', 'G'
            INVOKE RecordMove_v2, ADDR movesArray, '8', 'H'
            INVOKE RecordMove_v2, ADDR movesArray, '9', 'I'

            print   addr movesArray, 13, 10


            inkey " **************** E N D **************** "

            exit
;**************************************************************************

RecordMove    PROC      ptrArray:DWORD, cellChoice:DWORD, player:BYTE
   ;pushad
   
   mov edx, ptrArray                ; move array pointer to edx
   add edx, cellChoice
   
   mov al, player
   mov [edx], al                        ; <<< write al into edx address
   
   ;popad
   ret
   RecordMove    ENDP
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

RecordMove_v2    PROC      ptrArray:DWORD, cellChoice:BYTE, player:BYTE
   ;pushad
   
   mov edx, ptrArray                 ; move array pointer to edx

   movzx ecx, cellChoice             ; is ascii decimal digit
   sub   ecx, 31h                        ; convert from ascii code to integer 0,1,2,...,9
   
   mov al, player
   mov [edx+ecx], al
   
   ;popad
   ret
   RecordMove_v2    ENDP
;++++++++++++++++++++++++++++++++++++++++++++++
end start
; #############################################
Results:

abcdefghi
ABCDEFGHI
**************** E N D ****************

aw27

It is not necessary to use BYTE PTR if we let the assembler know the type of pointer we are using (MASM is smarter than most people believe). The pointer we require is a POINTER to a BYTE, so just spell that as PTR BYTE, not PTR, PTR DWORD, or even worse DWORD.


;\masm32\bin\ml /c /coff test.asm
;\masm32\bin\link /entry:main /SUBSYSTEM:CONSOLE test.obj

.model flat, stdcall

includelib \masm32\lib\msvcrt.lib
printf PROTO C :PTR, :VARARG
_getch PROTO C

RecordMove PROTO, ptrArray:PTR BYTE, index:DWORD, player:BYTE

.data
inputData db "this is my data",10,0
outputData BYTE LENGTHOF inputData DUP (0)

.code

main proc uses ebx esi
lea esi, inputData
mov ebx, 0

.while ebx<LENGTHOF inputData
INVOKE RecordMove, addr outputData, ebx, [esi+ebx]
inc ebx
.endw

invoke printf, addr outputData
invoke _getch
ret
main endp

RecordMove proc uses edi ptrArray:PTR BYTE, index:DWORD, player:BYTE
mov edi, ptrArray
mov edx, index
mov al, player
mov [edi+edx], al
ret
RecordMove endp

end

tenkey

QuoteProcedure definition:

RecordMove PROC, ptrArray:PTR DWORD, cellChoice : BYTE, player : BYTE
   pushad
   movzx esi, cellChoice         ; offset into array
   sub esi, 31h                      ; convert from ascii code to array offset
   mov al, player
   mov ptrArray[esi], al
   popad
   ret
   RecordMove ENDP


The idea here is that I use cellChoice as an offset into the array and then store player in that location. I suspect that I am using ESI incorrectly but I've used it like this in other code with no problems. Any other suggestions, corrections would be greatly appreciated.

ptrArray is being used incorrectly.
No instruction will fetch an address from memory and combine it into a new effective address. You must move the address (pointer) to a register.


       mov ecx,ptrArray   ;move address from memory to register
       movzx esi,cellChoice
       mov al,player
       mov byte ptr[ecx+esi],al

RuiLoureiro

#11
Hi tenkey,
           «mov   ptrArray[edx], eax» assembles without any error message:
           see RecordMove_v00, RecordMove_v01.
           In RecordMove_v02 we get the error message.
           
           But we know that riversr54 doesnt want to write into the stack
           but into movesArrayA, so he must move the pointer (from the stack)
           to a register as i wrote in reply #2 (but he didnt do it in reply #5).
         
Quote
;The difference btw DWORD, PTR BYTE, PTR WORD, PTR DWORD, PTR QWORD, etc
;No difference.
;
; When we want to pass the address to a ProcX we do
;
;                 push  offset ArrayX ; <<< this is always a DWORD in Win32
;                 call  ProcX
;
; ProcX   proc pArray:DWORD  ; <<< this is always a DWORD in Win32
;                              doesnt matter if data is BYTE,WORD,DWORD, etc.
;
;        HERE we must get the DWORD in pArray to a register
;         -----------------------------------------------------------
;         mov  edx, pArray
;
;         HERE the assembler doesnt know what kind of data it points to
;         ----------------------------------------------------------------------
;         ...
;         ret
; ProcX   endp
;
; If we have an array of words,dwords,bytes, ... we may use
; pArray:PTR WORD, pArray:PTR DWORD, pArray:PTR BYTE,...
; but it doesnt matter, it is always a DWORD in Win32.

; See the examples in the file TestAllCases.zip (we define one thing but we do ... something)

;***************************************************************************
RecordMove_v00    PROC ptrArray:DWORD, cellChoice:DWORD, player:BYTE
   
   mov   edx, cellChoice
   
   movzx eax, player
   mov   ptrArray[edx], eax    ; <<< it writes eax in the stack (?)
                               ;     ptrArray points to the stack
   ret
RecordMove_v00 ENDP
;***************************************************************************
RecordMove_v01    PROC ptrArray:PTR BYTE, cellChoice:DWORD, player:BYTE
   
   mov   edx, cellChoice
   
   movzx eax, player
   mov   ptrArray[edx], eax    ; <<< it writes eax in the stack
                               ;     ptrArray points to the stack
   ret
RecordMove_v01 ENDP 
;***************************************************************************
RecordMove_v02    PROC ptrArray:PTR BYTE, cellChoice:DWORD, player:BYTE
   
   mov   edx, cellChoice
   
   movzx eax, player
   mov   ptrArray[edx], al     ; <<< ERROR: instruction operands must be the same size
     
   ret
RecordMove_v02 ENDP                                                       

riversr54

Thanks for all the great replies. I've been away for a few days and am trying to understand everything that has been posted. Still learning...


RuiLoureiro

Quote from: riversr54 on October 19, 2018, 04:22:13 AM
Thanks for all the great replies. I've been away for a few days and am trying to understand everything that has been posted. Still learning...
I hope you have success... :biggrin: