### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Weird behavior of QWord  (Read 438 times)

#### domasz

• Full Member
• Posts: 142
##### Weird behavior of QWord
« on: November 27, 2022, 05:17:30 pm »
The code below:
Code: Pascal  [Select][+][-]
1. var buf: array[0..8] of Byte;
2.     Str: AnsiString = '123456789';
3.     i: Integer;
4.     w: QWord;
5. begin
6.   Move(Str[1], Buf[0], 9);
7.
8.   w := (buf[0] shl 56) or (buf[1] shl 48) or (buf[2] shl 40) or (buf[3] shl 32) or
9.        (buf[4] shl 24) or (buf[5] shl 16) or (buf[6] shl  8) or (buf[7]       );
10.
12.

gives 000000003536373C, which is not correct. But this code:
Code: Pascal  [Select][+][-]
1.
2.   Move(Str[1], Buf[0], 9);
3.
4.   w := 0;
5.   for i:=0 to 7 do w := (w shl 8) or buf[i];
7.

gives 3132333435363738 which is fine.

What am I missing here?

#### MarkMLl

• Hero Member
• Posts: 5866
##### Re: Weird behavior of QWord
« Reply #1 on: November 27, 2022, 05:22:15 pm »
The points made earlier about explicitly casting values to a qword. Somebody else- I think it was Martin- made similar points a few days ago.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### domasz

• Full Member
• Posts: 142
##### Re: Weird behavior of QWord
« Reply #2 on: November 27, 2022, 05:25:04 pm »
The points made earlier about explicitly casting values to a qword. Somebody else- I think it was Martin- made similar points a few days ago.

MarkMLl
Is "Martin" the full username here?

I also tried
Code: Pascal  [Select][+][-]
1. w := QWord(QWord(buf[0] shl 56) or QWord(buf[1] shl 48) or QWord(buf[2] shl 40) or QWord(buf[3] shl 32) or
2.        QWord(buf[4] shl 24) or QWord(buf[5] shl 16) or QWord(buf[6] shl  8) or QWord(buf[7]       ));
But gives the same result.

#### bytebites

• Hero Member
• Posts: 541
##### Re: Weird behavior of QWord
« Reply #3 on: November 27, 2022, 05:38:33 pm »
Code: Pascal  [Select][+][-]
1.   w := (qword(buf[0]) shl 56) or (qword(buf[1]) shl 48) or (qword(buf[2]) shl 40) or (qword(buf[3]) shl 32) or
2.        (qword(buf[4]) shl 24) or (qword(buf[5]) shl 16) or (qword(buf[6]) shl  8) or (qword(buf[7])       );

• Hero Member
• Posts: 12642
##### Re: Weird behavior of QWord
« Reply #4 on: November 27, 2022, 06:05:26 pm »
@bytebites
what a wonderful way to answer.

« Last Edit: November 27, 2022, 06:08:21 pm by Thaddy »
"Looks" OK, doesn't mean it is IS OK.

#### MarkMLl

• Hero Member
• Posts: 5866
##### Re: Weird behavior of QWord
« Reply #5 on: November 27, 2022, 07:26:55 pm »
Code: Pascal  [Select][+][-]
1. QWord(buf[0] shl 56)
2.

But gives the same result.

buf[0] is a byte. Shifting it by 56 bits still gives a byte, and the result will either be zero or 56 mod n where n is an implementation-defined power of 2.  Later converting it to a qword doesn't change the result of the shifting operation.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### domasz

• Full Member
• Posts: 142
##### Re: Weird behavior of QWord
« Reply #6 on: November 27, 2022, 07:45:17 pm »
Thank you!

#### dseligo

• Hero Member
• Posts: 901
##### Re: Weird behavior of QWord
« Reply #7 on: November 27, 2022, 11:54:28 pm »
Code: Pascal  [Select][+][-]
1. QWord(buf[0] shl 56)
2.

But gives the same result.

buf[0] is a byte. Shifting it by 56 bits still gives a byte, and the result will either be zero or 56 mod n where n is an implementation-defined power of 2.  Later converting it to a qword doesn't change the result of the shifting operation.

MarkMLl

I think it's not that simple.
Look at this as example:
Code: Pascal  [Select][+][-]
1. {\$R+}
2. var qw: QWord;
3.     b: Byte;
4. begin
5.   b := 1;
6.   qw := b shl 31;
7.   WriteLn(qw); // 2147483648
8.
9.   qw := b shl 32;
10.   WriteLn(qw); // 1
11.
12.   b := b + 30;
13.   qw := 1 shl b; // Runtime error 201 at \$000000010000169C
14.   WriteLn(qw);
15. end.

#### MarkMLl

• Hero Member
• Posts: 5866
##### Re: Weird behavior of QWord
« Reply #8 on: November 28, 2022, 08:47:00 am »
The first two are simple enough: it's been modded to 2**32. I concede the third is weird :-)

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

#### dseligo

• Hero Member
• Posts: 901
##### Re: Weird behavior of QWord
« Reply #9 on: November 28, 2022, 09:55:01 am »
The first two are simple enough: it's been modded to 2**32. I concede the third is weird :-)

Yes, but you said if variable is a byte, result will be byte as well.
So 32 bits is limit after which we have to cast variables?

Btw, this was on Windows 11, compiled to both 64 and 32 bit, FPC 3.2.2.
I tried on a Debian with FPC 3.2.2 and 3.3.1 and it is the same.

#### jamie

• Hero Member
• Posts: 5077
##### Re: Weird behavior of QWord
« Reply #10 on: November 28, 2022, 01:59:32 pm »
The first two are simple enough: it's been modded to 2**32. I concede the third is weird :-)

MarkMLl
No mystery there.

The constant on the left is converted to an Integer, which is 32 bits, the B is at that point 31, so the shift operation produces a negative integer which the Qword can't accept, because it does not have sign operations.

The compiler likes to magically convert every math operation to an integer regardless, unless of course you force Type Casting all over the place. I don't have this issue with Delphi, it seems to know better.

The only true wisdom is knowing you know nothing