Recent

Author Topic: misuse of integer types in asm block  (Read 1007 times)

Avinash

  • New Member
  • *
  • Posts: 25
misuse of integer types in asm block
« on: January 21, 2020, 08:57:04 am »
Such code is compiled but buggy. It should either not compile, like the one with Byte/Integer in Turbo Pascal, or, if it compile, it should work like in Virtual Pascal (afaik, I did not check).

Code: Pascal  [Select]
  1.   function Test: LongInt;
  2.   var W: Word;
  3.   begin
  4.     W := 1;
  5.     asm
  6.       mov eax, W
  7.       mov @Result, eax
  8.     end;
  9.   end;
  10.  
  11. begin
  12.   WriteLn(Test);
  13. end.

W := 1; compiles as mov word [ebp-8], 1

mov eax, W compiles as mov eax, dword [ebp-8]
               
Add: I remembered, in VP Word=DWord, that's why it compiled and worked there.
« Last Edit: January 21, 2020, 09:05:56 am by Avinash »

ccrause

  • Full Member
  • ***
  • Posts: 229
Re: misuse of integer types in asm block
« Reply #1 on: January 21, 2020, 09:34:40 am »
Dropping to pure asm mode puts more responsibility on the programmer. At least the compiler (3.0.4) gives a clear warning:
Code: Text  [Select]
  1. project1.lpr(10,14) Warning: Size suffix and destination or source size do not match

Quote
Such code is compiled but buggy.
Yes! it is the code that is buggy.

PascalDragon

  • Hero Member
  • *****
  • Posts: 958
  • Compiler Developer
Re: misuse of integer types in asm block
« Reply #2 on: January 21, 2020, 09:51:07 am »
As ccrause wrote the compiler explicitly warns you.

If you do a mov with a memory location then the assembler will use the width of the register as hint. So in this case you need to use a mov ax, W, though you also need to make sure that the upper 16-bit of EAX are cleared.

Avinash

  • New Member
  • *
  • Posts: 25
Re: misuse of integer types in asm block
« Reply #3 on: January 21, 2020, 10:17:03 am »
This is similar to typecasting. In your opinion, you can throw out typed language from pascal by allowing LongInt := Single without type conversion, leaving only an «nice explicit warning».
Turbo Pascal will compile mov ax, word ptr ByteVar, but without word ptr (typecast) it will out an error. This is a more correct behavior.

assembler will use the width of the register as hint
I think that .s files are generated by FPC for assembler, and not by assembler itself? These word[]/dword[] are already present in the .s file.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7926
Re: misuse of integer types in asm block
« Reply #4 on: January 21, 2020, 10:26:31 am »
assembler will use the width of the register as hint
I think that .s files are generated by FPC for assembler, and not by assembler itself? These word[]/dword[] are already present in the .s file.

The assembler is multilevel. The first level called the "assembler reader" reads pascal source and processes everything (ifdefs, pascal variable references etc) and generates so called "assembler lists".

Then an assembler writer generates the various forms of end output (the various textual assembler outputs, and, depending on target, a binary writer directly writes .o/.a)

ccrause

  • Full Member
  • ***
  • Posts: 229
Re: misuse of integer types in asm block
« Reply #5 on: January 21, 2020, 12:51:22 pm »
...
Turbo Pascal will compile mov ax, word ptr ByteVar, but without word ptr (typecast) it will out an error. This is a more correct behavior.
That is still buggy/incorrect in the context of the example in the first post:
Code: ASM  [Select]
  1.   mov eax, word ptr W
will still leave the high word of eax untouched.  Hence the next statement
Code: ASM  [Select]
  1.   mov @RESULT, eax
will put the random junk in the high word of eax into result.  As PascalDragon mentioned, the high word of eax needs to be cleared.  One option is to use the movzx instruction:
Code: ASM  [Select]
  1.   asm
  2.     movzx eax, word ptr W
  3.     mov @Result, eax
  4.   end;

PascalDragon

  • Hero Member
  • *****
  • Posts: 958
  • Compiler Developer
Re: misuse of integer types in asm block
« Reply #6 on: January 21, 2020, 02:46:08 pm »
This is similar to typecasting. In your opinion, you can throw out typed language from pascal by allowing LongInt := Single without type conversion, leaving only an «nice explicit warning».
No, it's not similar. Assembly is of the category "from great power comes great responsibility". It's your task to ensure that the assembly does what you intend, the compiler can't help you there (in this specific case both mov eax, word ptr ByteVar and mov eax, dword ptr ByteVar are valid, but have different results while LongInt := Single is not valid).

Turbo Pascal will compile mov ax, word ptr ByteVar, but without word ptr (typecast) it will out an error. This is a more correct behavior.
Despite FPC aspiring to be Turbo Pascal or Delphi compatible, FPC is not Turbo Pascal (or Delphi). There will always be differences and FPC's assembler reader is simply more forgiving. Not to mention that 32-bit or 64-bit x86 assembly is even more complex than 16-bit x86. And that FPC supports many more architectures than just x86...

assembler will use the width of the register as hint
I think that .s files are generated by FPC for assembler, and not by assembler itself? These word[]/dword[] are already present in the .s file.

As marcov wrote assembly code is handled in different levels. The readers are different from the writers and it is possible for example to read AT&T assembly, but have it write Intel assembly (in fact the RTL helpers on x86 are written using AT&T assembly). So the reader interprets your intention in a certain way, generates the necessary objects and then the writer will simply print that in a way that the called assembler is happy.

Avinash

  • New Member
  • *
  • Posts: 25
Re: misuse of integer types in asm block
« Reply #7 on: January 22, 2020, 03:54:43 am »
btw

Code: Pascal  [Select]
  1. .386
  2. .model flat
  3.   extrn ExitProcess:proc
  4. .data
  5.         Word    dw  1
  6.         DWord   dd  1
  7. .code
  8. start:
  9.  
  10.         mov   eax, Word
  11.  
  12.         push  0
  13.         call  ExitProcess
  14. end start

tasm32 /ml test.asm

(/ml,/mx,/mu    Case sensitivity on symbols: ml=all, mx=globals, mu=none)

Code: Pascal  [Select]
  1. Assembling file:   test.asm                        
  2. **Error** test.asm(10) Operand types do not match  
  3. Error messages:    1                              
  4. Warning messages:  None                            
  5. Passes:            1                              

to be holier than the Pope?
« Last Edit: January 22, 2020, 04:12:24 am by Avinash »

PascalDragon

  • Hero Member
  • *****
  • Posts: 958
  • Compiler Developer
Re: misuse of integer types in asm block
« Reply #8 on: January 22, 2020, 09:28:20 am »
In most cases there is a reason why something is the way it is (though of course there might be bugs as well). And in this case it is on purpose: you need to compile with range checks enabled (either -Cr on the command line or {$R+} in code) and the compiler will issue an error instead of a warning.

Avinash

  • New Member
  • *
  • Posts: 25
Re: misuse of integer types in asm block
« Reply #9 on: January 22, 2020, 01:28:49 pm »
I can in the same way in pascal assign any type to any other type, but this is not a reason to make this possible by default.
Code: Pascal  [Select]
  1. VarOneType := TOneType((@VarAnyOtherType)^);

Thaddy

  • Hero Member
  • *****
  • Posts: 9622
Re: misuse of integer types in asm block
« Reply #10 on: January 22, 2020, 01:45:18 pm »
Yet that is exactly what you are doing.....Either your assembler skills lack or your understanding. My guess is the former, so don't use assembler.
You might have noticed TP basm and (early) Delphi basm is notoriously inaccurate too: it requires massaging into what you want.
« Last Edit: January 22, 2020, 01:51:49 pm by Thaddy »
I am more like donkey than shrek

PascalDragon

  • Hero Member
  • *****
  • Posts: 958
  • Compiler Developer
Re: misuse of integer types in asm block
« Reply #11 on: January 23, 2020, 09:40:00 am »
I can in the same way in pascal assign any type to any other type, but this is not a reason to make this possible by default.
Code: Pascal  [Select]
  1. VarOneType := TOneType((@VarAnyOtherType)^);

As said there likely is a valid reason why it behaves like it does, but I can't tell you, because this was introduced before the change to SVN.