I'm still confused with the use of MOV, BYTE PTR, and 32 bit registers addressing.
if I have a BYTE variable defined as:
MyByte db 151
and I want to MOV it to a 32 byte address in EAX how do I change this:
mov [eax], MyByte ?
This obviously gives an error because the two operands are not the same size.
Nor it works this way:
mov byte ptr [eax], MyByte
The following works:
lea eax, MyByte
mov eax, [eax]
Quote from: Gunner on September 04, 2010, 10:34:26 PM
The following works:
lea eax, MyByte
mov eax, [eax]
Thanks Gunner.
This works but it is indirect, I was trying to do it in a single instruction.
I think there is another way as well, but I can't remember how to use MOV
and BYTE PTR to get it working.
Frank,
; move byte from memory to eax:
xor eax,eax ; if you dont want have only value of byte, you can not write this line
mov al,byte ptr [anyLabel]
Or you can use this:
movzx eax,byte ptr [anyLabel]
Second code makes only value of byte in eax - this command zeroed other high bytes.
Alex
Quote from: Antariy on September 04, 2010, 10:43:28 PM
Frank,
; move byte from memory to eax:
xor eax,eax ; if you dont want have only value of byte, you can not write this line
mov al,byte ptr [anyLabel]
Or you can use this:
movzx eax,byte ptr [anyLabel]
Thanks Alex, but this is not what I need.
I have this variable:
MyByte db 151and I want to MOV it to a 32 byte address that is in EAX.
I need to move the byte to [eax] not to eax.I need only 1 byte mov to 1 byte in memory, without changing others bytes
that are in memory.
These don't work:
1. mov [eax], MyByte
2. mov byte ptr [eax], MyByte
3. lea ebx, MyByte
mov [eax], [ebx]
I'm looking for an instruction that moves the content of MyByte variable
into the address that is in EAX, nothing else.
Frank
Frank, try this:
movzx ecx,byte ptr [MyByte]
mov byte ptr [eax],cl
Alex
Frank, the general rule: you cannot move memory to memory, you must use intermediate code.
Alex
Quote from: Antariy on September 04, 2010, 11:07:07 PM
Frank, try this:
movzx ecx,byte ptr [MyByte]
mov byte ptr [eax],cl
Alex
OK Alex this works. Thanks :U
Look at movsb.
Quote from: jj2007 on September 05, 2010, 07:18:34 AM
Look at movsb.
INTEL says:
Quote
Description
Moves the byte, word, or doubleword specified with the second operand (source
operand) to the location specified with the first operand (destination operand). Both
the source and destination operands are located in memory. The address of the
source operand is read from the DS:ESI or the DS:SI registers (depending on the
address-size attribute of the instruction, 32 or 16, respectively). The address of the
destination operand is read from the ES:EDI or the ES:DI registers (again depending
on the address-size attribute of the instruction). The DS segment may be overridden
with a segment override prefix, but the ES segment cannot be overridden.
At the assembly-code level, two forms of this instruction are allowed: the "explicitoperands"
form and the "no-operands" form. The explicit-operands form (specified
with the MOVS mnemonic) allows the source and destination operands to be specified
explicitly. Here, the source and destination operands should be symbols that
indicate the size and location of the source value and the destination, respectively.
This explicit-operands form is provided to allow documentation; however, note that
the documentation provided by this form can be misleading. That is, the source and
destination operand symbols must specify the correct type (size) of the operands
(bytes, words, or doublewords), but they do not have to specify the correct location.
The locations of the source and destination operands are always specified by the
DS:(E)SI and ES:(E)DI registers, which must be loaded correctly before the move
string instruction is executed.
The no-operands form provides "short forms" of the byte, word, and doubleword
versions of the MOVS instructions. Here also DS:(E)SI and ES:(E)DI are assumed to
be the source and destination operands, respectively. The size of the source and
destination operands is selected with the mnemonic: MOVSB (byte move), MOVSW
(word move), or MOVSD (doubleword move).
After the move operation, the (E)SI and (E)DI registers are incremented or decremented
automatically according to the setting of the DF flag in the EFLAGS register.
(If the DF flag is 0, the (E)SI and (E)DI register are incremented; if the DF flag is 1,
the (E)SI and (E)DI registers are decremented.) The registers are incremented or
decremented by 1 for byte operations, by 2 for word operations, or by 4 for doubleword
operations.
The MOVS, MOVSB, MOVSW, and MOVSD instructions can be preceded by the REP
prefix (see "REP/REPE/REPZ /REPNE/REPNZ—Repeat String Operation Prefix" in
Chapter 4 of the Intel® 64 and IA-32 Architectures Software Developer's Manual,
Volume 2B, for a description of the REP prefix) for block moves of ECX bytes, words,
or doublewords.
It seems that to use MOVSB I need to fill ESI for source address and EDI for target address.
It could be useful If I had to MOV 11 bytes, for example, using REP/MOVSB and putting
11 into ECX for contiguous addresses.
In my case I only need to move The same BYTE variable to different non contiguous addresses.
To be exact I need to move the BYTE variable to an area every fourth bytes:
x---x---x---x---x---x
the "x" represent the addresses into a memory block at which I have to MOV the BYTE variable.
the "-" represent the addresses occupied by other values that I have to leave where they are.
In this case I should manually change EDI before each MOV.
Or at least this is what I think.
I'm using Alex suggestion, and having the destination address in EAX, I do:
movzx ebx, byte ptr [MyByte]
mov ecx, 11
Again:
mov byte ptr [eax],bl
add eax, 4
dec ecx
jnz Again
There is any advantage for using MOVSB instead of the mnemonics I'm
actually using?
It would change this way:
lea edi, MyByte
lea esi, MyDestination
mov ecx, 11
Again:
movsb
add esi, 3
dec edi
dec ecx
jnz Again
If I correctly understood what MOVSB does.
And it doesn't look like a better solution than the previous one.
Frank
The complete code in which I'm using these mnemonics is a proc for
building a Box inside a buffer:
; -------------------------------------------------------------------------
; Fill the buffer with a box of 80 characters starting at line requested
; till the number of line passed as II parameter
;--------------------------------------------------------------------------
BuildBox PROC Row1:DWORD, Row2:DWORD
mov eax, Row1
sub eax, 1
imul eax, 320
mov edx, eax
lea eax, ConsoleScreen
add eax, edx
movzx ebx, byte ptr [TopLeft]
mov byte ptr [eax],bl
add eax, 4
mov ecx, 78
movzx ebx, byte ptr [HorizLine]
mov bl, HorizLine
FillBoxLine1:
mov byte ptr [eax], bl
add eax, 4
dec ecx
jnz FillBoxLine1
movzx ebx, byte ptr [TopRight]
mov byte ptr [eax], bl
add eax, 4
mov ecx, Row2
sub ecx, Row1
dec ecx
movzx ebx, byte ptr [VerticLine]
FillBorder:
mov byte ptr [eax], bl
add eax, 4
mov edx, 4
imul edx, 78
add eax, edx
mov byte ptr [eax], bl
add eax, 4
dec ecx
jnz FillBorder
movzx ebx,byte ptr [BottomLeft]
mov byte ptr [eax], bl
add eax, 4
mov ecx, 78
movzx ebx, byte ptr [HorizLine]
FillBoxLine2:
mov byte ptr [eax], bl
add eax, 4
dec ecx
jnz FillBoxLine2
movzx ebx, byte ptr [BottomRight]
mov byte ptr [eax], bl
ret
BuildBox ENDP
If I can improve this routine getting rid of redundant instructions just
let me know how would you change this code.
Frank
Quote from: frktons on September 05, 2010, 10:17:28 AM
The complete code in which I'm using these mnemonics is a proc for
building a Box inside a buffer:
; -------------------------------------------------------------------------
; Fill the buffer with a box of 80 characters starting at line requested
; till the number of line passed as II parameter
;--------------------------------------------------------------------------
BuildBox PROC Row1:DWORD, Row2:DWORD
mov eax, Row1
sub eax, 1
imul eax, 320
mov edx, eax
lea eax, ConsoleScreen
add eax, edx
movzx ebx, byte ptr [TopLeft]
mov byte ptr [eax],bl
add eax, 4
mov ecx, 78
movzx ebx, byte ptr [HorizLine]
mov bl, HorizLine
FillBoxLine1:
mov byte ptr [eax], bl
add eax, 4
dec ecx
jnz FillBoxLine1
movzx ebx, byte ptr [TopRight]
mov byte ptr [eax], bl
add eax, 4
mov ecx, Row2
sub ecx, Row1
dec ecx
movzx ebx, byte ptr [VerticLine]
FillBorder:
mov byte ptr [eax], bl
add eax, 4
mov edx, 4
imul edx, 78
add eax, edx
mov byte ptr [eax], bl
add eax, 4
dec ecx
jnz FillBorder
movzx ebx,byte ptr [BottomLeft]
mov byte ptr [eax], bl
add eax, 4
mov ecx, 78
movzx ebx, byte ptr [HorizLine]
FillBoxLine2:
mov byte ptr [eax], bl
add eax, 4
dec ecx
jnz FillBoxLine2
movzx ebx, byte ptr [BottomRight]
mov byte ptr [eax], bl
ret
BuildBox ENDP
If I can improve this routine getting rid of redundant instructions just
let me know how would you change this code.
Frank
Tip 1: You dont need "byte ptr" when the assembler knows you are using an 8 bit register. You really only need it when referencing memory, not a register.
Tip 2: You use the number "4", four times up there. Move the number 4 to a register and use the register instead of a constant number.
Tip 3: When calculating the offset of different lines, consider the cmov instructions instead of using complex jump structures. cmovb will move a value into the number if the number is below the given number (for example). cmova will move the value if the value is above etc. And when dealing with the 80x25 screen you can implement smart shifting for calculating offset.
As a final note, it can be done alot more efficient but it takes a bit of planning to do so.
Quote from: zemtex on September 05, 2010, 01:33:02 PM
Tip 1: You dont need "byte ptr" when the assembler knows you are using an 8 bit register. You really only need it when referencing memory, not a register.
Tip 2: You use the number "4", four times up there. Move the number 4 to a register and use the register instead of a constant number.
Tip 3: When calculating the offset of different lines, consider the cmov instructions instead of using complex jump structures. cmovb will move a value into the number if the number is below the given number (for example). cmova will move the value if the value is above etc. And when dealing with the 80x25 screen you can implement smart shifting for calculating offset.
As a final note, it can be done alot more efficient but it takes a bit of planning to do so.
Thanks for the Tips, zemtex. I'll try to put them in use as far as I can with my actual knowledge.
If you have some spare time and would like to enjoy a CHALLENGE, have a look at:
http://www.masm32.com/board/index.php?topic=14734.0
Frank