VB6: Конечно, это простое шестнадцатеричное дополнение неверно? - PullRequest
4 голосов
/ 19 февраля 2009

Я получаю странные результаты в некотором коде VB6, который я сузил до следующего:

Debug.Print Hex(&hEDB80000 + &h8300)

Показывает EDB78300

Это не может по праву, не так ли? Конечно, это должно быть EDB88300 ?

Я схожу с ума?

Ответы [ 2 ]

15 голосов
/ 19 февраля 2009

Не забывайте, как отрицательные числа выражаются в двоичном , и что VB6 и VB.NET по-разному интерпретируют числа, такие как & h8300.

Поскольку & hEDB80000 не умещается в 16 бит, VB интерпретирует его как long (32 бита). Поскольку старший бит установлен, VB6 знает, что он отрицательный.

Давайте отменим дополнение два (в 32-битном мире), чтобы вычислить десятичное значение

(~&hEDB80000 + 1) = &h1247FFFF + 1 = &h12480000 = 306708480 

поскольку бит знака был установлен, это -306708480

Поскольку & h8300 вписывается в 16-битное значение, VB интерпретирует его как целое число (16-битное значение). Поскольку старший бит установлен, VB6 знает, что он отрицательный.

Давайте отменим дополнение к двум (в 16-битном мире)

(~&h8300 + 1) = &h7DFF + 1 = &h7D00 = 32000

поскольку бит знака был установлен, это -32000 . Когда происходит сложение, оба значения считаются длинными (32-битными).

(-306708480) + (-32000) = -306740480

Давайте поместим это обратно в гекс дополнения до двух

~(306740480 - 1) = ~(&h12487D00 - 1) = ~(&h12487CFF) = &hEDB78300

Итак, & hEDB78300 - правильный ответ.


Примечания:

Лично я считаю, что путаница происходит из-за следующего:

&h0004000 is interpreted as  16384 // Fits in 16-bits, sign bit is not set
&h0008000 is interpreted as -32768 // Fits in 16-bits, sign bit is set
&h0010000 is interpreted as  65536 // Requires 32-bits, sign bit is not set

как упоминалось в другом посте, вы можете обойти это, явно пометив значения как longs

&h0004000& is interpreted as  16384 
&h0008000& is interpreted as  32768 
&h0010000& is interpreted as  65536 
3 голосов
/ 19 февраля 2009

По сути, потому что VB6 видит & h8300 как целое число со значением -32000. Чтобы получить ожидаемые результаты, вам нужно явно пометить его как Long: -

Debug.Print Hex(&hEDB80000 + &h8300&)

То, что вы делали, добавляло Long к Interger. Для этого VB6 сначала расширяет Integer на Long, поскольку & h8300 представляет отрицательное число, для которого Long конвертируется и заканчивается значением & hFFFF8300. Вооружившись этим значением, вы можете видеть, что результат, возвращаемый VB6, правильный.

FF + B8 = B7 with carry bit set
FF + ED + carry bit = ED
...