Error A2048: must be the same size: 4 - 8 and Error A2071: Invalid operand size

Started by LiaoMi, June 07, 2022, 05:05:32 AM

Previous topic - Next topic

LiaoMi

Hi,

UASM cannot determine the type of variables on all possible variations, for example

    and al,NOT(SET)
    and [ebx].COBii[USER.Look],(1 shl GR) or (1 shl GR)
    or [ebx].COBii[USER.J],eax


Multiple error messages look like this>
Error A2048: Operands must be the same size: 4 - 8
Error A2048: Operands must be the same size: 1 - 2
Error A2071: Invalid operand size for instruction


Then I have to rewrite the code>
and al,NOT byte PTR (SET)
or dword ptr  [ebx].COBii[USER.J],eax


JWASM documentation writes - https://wiki.osdev.org/JWasm
Quote
Abbreviated Notation
This notation is a fully specified format which occurs in the following form:

    mov eax, DWORD PTR [edi]
Over time, the parsers in assemblers have improved to the stage where if the assembler can recognize the size of the data then the SIZE specifier may be omitted as such.

    mov eax, [edi]
This allows for clearer code that is easier to read. However, there are some contexts where the assembler cannot independently determine the data size; For example, if the source operand is a memory operand. In this situation the historical data SIZE specifiers must be used. The following is an example of this situation.

    movzx eax, [esi]            ; generates an error - data SIZE cannot be determined by the assembler
    movzx eax, BYTE PTR [esi]   ; zero extend a BYTE into the 32 bit EAX register


The same code is well understood by the original macro assembler. In which you do not need to add anything, I consider it as violation in compatibility.

In addition, there is another error with UASM: fatal error LNK1107: invalid or corrupt file: cannot read at 0x15AB

mainMasm.asm(78) : Error A2048: Operands must be the same size: 1 - 2
mainMasm.asm(79) : Error A2071: Invalid operand size for instruction
mainMasm.asm(80) : Error A2048: Operands must be the same size: 8 - 4
mainMasm.asm: 101 lines, 1 passes, 1 ms, 0 warnings, 3 errors
Microsoft (R) Incremental Linker Version 14.29.30037.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Because of these errors, I can't assemble a large project  :biggrin:, editing the entire code can't be a solution either  :skrewy:, Microsoft assembler works without errors :badgrin:

jj2007

    mov ebx, offset COA

;    assume ebx:PTR _COA avoid this syntax, no good for readability
    Obi equ [ebx._COA.COBii] ; much better
   
    and al, NOT(GET) ; NO fatal error LNK1107 here with polink - which linker do you use?
    int 3 ; have a look...
    and al, NOT(SET) ; -205... does it really fit into a byte? MASM thinks it does, UAsm disagrees
    and ax, NOT(SET) ; works for UAsm and MASM
    and eax, NOT(SET) ; works for UAsm and MASM
    and [ebx._COA.COBii.Look], (1 shl GR) or (1 shl GR)
    or [ebx._COA.COBii.J],eax
    or Obi.J, eax ; isn't that cute?


Quote from: LiaoMi on June 07, 2022, 05:05:32 AM    movzx eax, [esi]            ; generates an error - data SIZE cannot be determined by the assembler
    movzx eax, BYTE PTR [esi]   ; zero extend a BYTE into the 32 bit EAX register


The same code is well understood by the original macro assembler. In which you do not need to add anything, I consider it as violation in compatibility.

What exactly do you mean? MASM allows movzx eax, [esi]???

LiaoMi

Hi jj2007,

I meant just my attached example, without taking into account the quote from the documentation.

An example is below:
mainMasm.obj : fatal error LNK1107: invalid or corrupt file: cannot read at 0x15C5

Microsoft (R) Incremental Linker Version 14.29.30037.0

1 byte is 255, SET equ 11001100B - > 204 - > NOT 204 - > 51 
Where does the negative number come from?

jj2007

polink doesn't like your object file...

\Masm32\Members\LiaoMi\UasmBug>\Masm32\bin\polink /SubSystem:console /machine:x86 mainMasm.obj
POLINK: fatal error: Invalid machine type in object 'mainMasm.obj'.

tenkey

Quote from: LiaoMi on June 07, 2022, 07:43:49 AM
1 byte is 255, SET equ 11001100B - > 204 - > NOT 204 - > 51 
Where does the negative number come from?

32- or 64-bit arithmetic and logic

NOT CCh --> FFFFFF33h --> -205, which is less than -128

LiaoMi

Hi jj2007,

the difference is in the three lines that are commented out, assembly was done using UASM:

Quoteand al,NOT(GET) ; < BUG - fatal error LNK1107: invalid or corrupt file: cannot read at 0x15AB
    ;and al,NOT(SET)
    ;and [ebx].COBii[USER.Look],(1 shl GR) or (1 shl GR)
    ;or [ebx].COBii[USER.J],eax

I couldn't find any additional information on how it should be correct ... operator NOT - https://docs.microsoft.com/en-us/cpp/assembler/masm/operator-not?view=msvc-170. In the new example, the object file also turns out to be broken. :rolleyes:

or Obi.J, eax ; isn't that cute?
:biggrin: Yes, it looks cute! I've never seen this type of writing before.  I also liked your user archive  :thumbsup:  :biggrin: \Masm32\Members\LiaoMi\

Quote from: tenkey on June 07, 2022, 03:59:02 PM
Quote from: LiaoMi on June 07, 2022, 07:43:49 AM
1 byte is 255, SET equ 11001100B - > 204 - > NOT 204 - > 51 
Where does the negative number come from?

32- or 64-bit arithmetic and logic

NOT CCh --> FFFFFF33h --> -205, which is less than -128
:thumbsup: My calculator showed the wrong thing, but everything is fine in the Windows calculator  :biggrin: Thanks!

jj2007

Quote from: LiaoMi on June 08, 2022, 01:50:05 AMor Obi.J, eax ; isn't that cute?
:biggrin: Yes, it looks cute! I've never seen this type of writing before.

The equate Obi equ [ebx._COA.COBii] can be changed any time, in case you want to use edi, for example: Obi equ [edi._COA.COBii].
I try to stick to one index register, in order to avoid confusion.

Re NOT: I don't think there is a scientifically correct answer. It's a matter of interpretation. Masm sees a BYTE, the Watcom assemblers see 32-bit arithmetic. Avoid this kind of acrobatics...

LiaoMi

Quote from: jj2007 on June 08, 2022, 02:30:52 AM
Re NOT: I don't think there is a scientifically correct answer. It's a matter of interpretation. Masm sees a BYTE, the Watcom assemblers see 32-bit arithmetic. Avoid this kind of acrobatics...

"First, the macro doesn't compute anything. It is substituted into a source code, expanded, and the resulting text gets compiled. What the resulting text is, depends on the way you use the macro, especially on what parameter you give."

"For a negative decimal number, the MACRO must form its absolute value as a positive number."

GETa equ -88
GETb equ (-88)
GETc equ 88
GETd equ -88t


    mov al, GETa
    mov al, GETb
    mov al, GETc
    mov al, GETd


mov     al, 0A8h
mov     al, 0A8h
mov     al, 58h ; 'X'
mov     al, 0A8h


        /*  A public EQU can be negative, so must adjust value */
        /* this brain damage is happening because masm keeps numbers
         * in 17/33 bit sign magnitude representation */

        if ((pglob->symkind == EQU) && pglob->symu.equ.equrec.expr.esign)
                pubvalue = (short)(((use32==0x91? 0xffffffffl : 65535) - pglob->offset) + 1);



But macros must treat values as absolute, otherwise it contradicts the code itself, which uses the byte register. Therefore, I believe that the processing in MASM from Microsoft is logically correct.


In another case:
"H2INC places an OPTION EXPR32 directive in the .INC file so that MASM
correctly handles long integers within expressions. This means that the .INC files as
well as all the .ASM files which include .INC files created with H2INC will resolve
integer expressions in 32 bits instead of 16 bits.
This also means that if a negative number is evaluated in an expression, its value
can only be used as a double word (or longer) operand.
These C statements:
#define MINUS_1 (-1)
#define MINUS_2 -2

generate these MASM statements:
MINUS_1 EQU 0ffffffffh
MINUS_2 EQU -2t

In most cases, the second behavior is more desirable, as the decimal representation
can be cast within MASM to the appropriate size (with a word ptr operator, for
example)."

MASM
GETa equ -88
GETb equ (-88)
GETc equ 88
GETd equ -88t


    mov al, GETa
    mov al, GETb
    mov al, GETc
    mov al, GETd
   
    mov ax, word ptr GETa
    mov ax, word ptr GETb
    mov ax, word ptr GETc
    mov ax, word ptr GETd
   
    mov ax, byte ptr GETa
    mov ax, byte ptr GETb
    mov ax, byte ptr GETc
    mov ax, byte ptr GETd
   
    mov al, NOT(GETa)
    mov al, NOT(GETb)
    mov al, NOT(GETc)
    mov al, NOT(GETd)


mov     al, 0A8h
mov     al, 0A8h
mov     al, 58h ; 'X'
mov     al, 0A8h

mov     ax, 0FFA8h
mov     ax, 0FFA8h
mov     ax, 58h ; 'X'
mov     ax, 0FFA8h

mov     ax, 0FFA8h
mov     ax, 0FFA8h
mov     ax, 58h ; 'X'
mov     ax, 0FFA8h

mov     al, 57h ; 'W'
mov     al, 57h ; 'W'
mov     al, 0A7h
mov     al, 57h ; 'W'


UASM

                 mov     al, 0A8h
_TEXT:00000087                 mov     al, 0A8h
_TEXT:00000089                 mov     al, 58h ; 'X'
_TEXT:0000008B                 mov     al, 0A8h

_TEXT:0000008D                 mov     ax, 0FFA8h
_TEXT:00000091                 mov     ax, 0FFA8h
_TEXT:00000095                 mov     ax, 58h ; 'X'
_TEXT:00000099                 mov     ax, 0FFA8h

_TEXT:0000009D                 mov     ax, 0FFA8h
_TEXT:000000A1                 mov     ax, 0FFA8h
_TEXT:000000A5                 mov     ax, 58h ; 'X'
_TEXT:000000A9                 mov     ax, 0FFA8h

_TEXT:000000AD                 mov     al, 57h ; 'W'
_TEXT:000000AF                 mov     al, 57h ; 'W'
_TEXT:000000B1                 mov     al, 0A7h
_TEXT:000000B3                 mov     al, 57h ; 'W'


Once the numbers become negative, UASM can't work with them. Here it is required to make a mandatory casting of a variable using byte ptr, which makes no sense, because the register itself tells about the size of the variable. In any case, the object file becomes broken.  :undecided: