News:

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

Main Menu

What is the difference between WORD and WORD PTR

Started by StillLearningMasm, July 16, 2023, 04:50:37 PM

Previous topic - Next topic

StillLearningMasm

I receintly learned that MASM supports using BYTE, WORD etc without having PTR after it.
What is the difference between WORD and WORD PTR?

I created this code fragment:
mov ax, word [bx]
mov ax, word ptr [bx]

That creates this code:
 00000018  67& 66| 8B 47   mov ax, word [bx] ;same as mov ax,[bx + 2]
      02

 0000001D  67& 66| 8B 07   mov ax, word ptr [bx] ;same as mov ax,[bx]

So what is PTR? I thought it might be the same as offset but it dpesn't seem to be and MASM does a terrible way of explaining it for me.

Thank you,
StillLearningMasm


NoCforMe

Hmm, not sure what assembler you're using, but WORD by itself is meaningless.
WORD PTR means to treat the source operand as a word. It's basically an override of the usual behavior. Commonly used when you're loading a word-size register from something larger, like a doubleword:

    MOV    AX, WORD PTR [DWORD variable]        ;Loads low word of var.
    MOV    AX, WORD PTR [DWORD variable + 2]    ;Loads high word of var.

Didn't the statement with just WORD give you an error?
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on July 16, 2023, 06:38:02 PMHmm, not sure what assembler you're using, but WORD by itself is meaningless.
...
Didn't the statement with just WORD give you an error?

Indeed. I tested it with a variety of assemblers, and they all give an error.

zedd151

What version of ml.exe StillLearningMasm? Or is it ml64? Or is it different assembler? Still, there may be a buggy assembler, would be good to know the name and version so others may avoid having the issue you described.

daydreamer

Most usage i done/seen with all kinds of byte ptr,word ptr,dword ptr,qword ptr,real4 ptr,real8 ptr,real10 ptr is using fpu indirect memory adresses
Fld [ebx] real4 ptr
Without "real4 ptr " the Assembler is unable to guess if you want to load a real4,real8,real10,so you get an error
I am not sure if
movz eax,[ebx] byte ptr
Movz eax,[ebx] word ptr
Is needed
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

NoCforMe

Let's try to keep this simple; the OP is just learning assembler, so no need to further confuse them.

When you transfer data between two things (registers or memory variables) that are the same size, the assembler knows what you're trying to do, so there's no need for any PTR modifiers.

If you're transferring data between two different sized entities, the assembler will throw an error unless you specify that this is what you want to do, by using the PTR modifier:

    MOV    EAX, DWORD_size_variable            ;Same size, no PTR needed
    MOV    AL, BYTE PTR DWORD_size_variable    ;Taking a BYTE out of a DWORD, so need BYTE PTR
    MOV    AX, WORD PTR DWORD_size_variable    ;Having a WORD w/a DWORD, so need WORD PTR

These examples are where the source (the right-hand side) is larger than the destination. You can also do the opposite, loading a larger entity from something defined as a smaller entity:

    MOV    EAX, DWORD PTR BYTE_defined_variable

where a variable defined using DB actually contains a DWORD value (weird, but legal; the variable would have to be at least 4 bytes long for this to work).

Does that make sense now? It's basically another way to get into trouble with the assembler, unless you know what you're doing.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Here's a real-world example of where you'd need to use PTR. Let's say your program handles the WM_MOUSEMOVE message from Windows, which is sent anytime the mouse moves over one of your windows. The lParam parameter of this message contains the X- and Y-coordinates of the mouse, packed into a DWORD. To get them into two registers you'd use:

    MOV    AX, WORD PTR lParam            ;X-coord. of mouse
    MOV    DX, WORD PTR lParam + 2        ;Y-coord. of mouse

What the first statement does is load a WORD-sized register from a variable that's defined as a DWORD. It loads the low word of the variable--the first 16 bits of the 32-bit variable.

The 2nd statement loads the high word of the variable--the last 16 bits. You need to keep in mind that the X86 processor is "little-endian", which means the low byte/word/doubleword comes before the high byte/word/doubleword, unlike "big-endian" CPUs like the 68000.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Lastly, hopefully not to confuse you, but here's how you'd really do this in a real-world program (get the mouse coords. into 2 registers). The problem with the previous example is that you have 2 WORD-size registers, which don't really work too well in a 32-bit program. We'd rather have them in EAX and EDX, instead of AX and DX.

No problemo; we'll just use:

    MOVZX    EAX, WORD PTR lParam            ;X-coord. of mouse
    MOVZX    EDX, WORD PTR lParam + 2        ;Y-coord. of mouse

The MOVZX is a really cool instruction that can move a WORD into a DWORD-size register, and fill the other 16 bits with zeroes. (MOVSX does the same thing but copies the sign bit into the upper 16 bits, to preserve the sign of an integer.) WORD PTR is needed here to tell the assembler that we want to take 16 bits from the source.
Assembly language programming should be fun. That's why I do it.

StillLearningMasm

Here is the code we discussed:

;using MASM version 6 (supports version 5 by using OPTION M510)
option M510

    .386
    .model tiny

    .code

mov al,byte [bx] ;same as mov al,[bx + 1] (no error message)
; (syntax error if no OPTION M510)
mov al,byte ptr [bx] ;same as mov al,[bx]
mov ax, word [bx] ;same as mov ax,[bx + 2] (no error message)
; (syntax error if no OPTION M510)
mov ax, word ptr [bx] ;same as mov ax,[bx]
mov eax, dword [bx] ;same as mov eax,[bx + 4] (no error message)
; (syntax error if no OPTION M510)
mov eax, dword ptr [bx] ;same as mov eax,[bx]

;below are the same examples without size specified for indirect memory
;no errors
mov al,[bx + 1]
mov al,[bx]
mov ax,[bx + 2]
mov ax,[bx]
mov eax,[bx + 4]
mov eax,[bx]

    .data
end

jj2007

> supports version 5 by using OPTION M510

That could be the problem: Version 5 is 35 years old, and guess what? It wasn't perfect.

Do you have a specific reason to use 16-bit code?

NoCforMe

I guess JJ's question is a valid one. You seem to be mixing 16- and 32-bit code, which doesn't work well.

One statement of yours in particular is kind of Frankenstinian:

mov eax, dword [bx] ;same as mov eax,[bx + 4] (no error message)

The problem is that this is obviously 32-bit code (since you're using EAX), but you're trying to address memory with a 16-bit pointer ([BX]). That probably ain't gonna work.

And I don't see how you can say that mov eax, dword ptr [bx] is the same as mov eax, [bx + 4]. Is that what assembly listing is showing? Seems to me it should be [bx + 0], since you haven't specified a 4-byte offset here. Maybe that's another bug with that old assembler, or a result of a strange instruction construct. In any case, not valid.

Anyhow, looks like you might want to untangle the 32-bit stuff from the 16-bit stuff. (You can still write 16-bit code if you really want to, though it's hard to see a reason why you'd choose that path; that's the bad old world of DOS ...)
Assembly language programming should be fun. That's why I do it.

_japheth

Quote from: NoCforMe on July 17, 2023, 07:28:50 AMmov eax, dword [bx] ;same as mov eax,[bx + 4] (no error message)

The problem is that this is obviously 32-bit code (since you're using EAX), but you're trying to address memory with a 16-bit pointer ([BX]). That probably ain't gonna work.

Using 32-bit registers is perfectly valid in "16-bit code" and works quite well.

QuoteAnd I don't see how you can say that mov eax, dword ptr [bx] is the same as mov eax, [bx + 4].

If a type like "DWORD" is used without the PTR operator, masm assumes that it's meant to be a short form of "TYPE DWORD", and therefore gives the result 4.

That why masm - even the newer versions - will accept this syntax:

mov eax, [dword] [bx]          ; same as "mov eax,[bx+4]"


Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

NoCforMe

Quote from: _japheth on July 17, 2023, 06:47:54 PMUsing 32-bit registers is perfectly valid in "16-bit code" and works quite well.

Hmm; don't you mean "using 16-bit registers is perfectly valid in 32-bit code"? Which is true; you can access BX as well as BL and EBX. The reason I said it probably wouldn't work is that a 16-bit memory access might well be illegal, at least judging from the addresses I see in OllyDbug with Windows programs. But yes, you can use them (16-bit regs) if you know what you're doing.

Quote
QuoteAnd I don't see how you can say that mov eax, dword ptr [bx] is the same as mov eax, [bx + 4].

If a type like "DWORD" is used without the PTR operator, masm assumes that it's meant to be a short form of "TYPE DWORD", and therefore gives the result 4.

That why masm - even the newer versions - will accept this syntax:

mov eax, [dword] [bx]          ; same as "mov eax,[bx+4]"

Ah, I see. Didn't know that (about TYPE). It's doing what it's supposed to do, but the result is bizarre and not what the OP was looking for.
Assembly language programming should be fun. That's why I do it.

FORTRANS

Hi,

Quote from: NoCforMe on July 17, 2023, 07:02:13 PM
Quote from: _japheth on July 17, 2023, 06:47:54 PMUsing 32-bit registers is perfectly valid in "16-bit code" and works quite well.

Hmm; don't you mean "using 16-bit registers is perfectly valid in 32-bit code"?

  No, using 32-bit registers works well in 16-bit (MS-DOS) code.  You
do use 16-bit addressing.  Just as you would use 32-bit addressing in
32-bit (Windows) code using 16-bit registers.  Not to mention using 8-bit
registers in either mode.

Cheers,

Steve N.

zedd151

@FORTRANS:

It is a case of:
Quote from: hutch-- on July 19, 2016, 09:43:29 AM:biggrin:

MASM does not have bugs, it just has features you need to understand.  :P
:biggrin: