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
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.
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
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".
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
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.
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
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.
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 ****************
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
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
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
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...
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: