Преобразование какой-либо сборки в VB.NET - оператор SHR работает по-другому? - PullRequest
3 голосов
/ 12 июля 2010

Ну, простой вопрос здесь

Я изучаю некоторые сборки и конвертирую некоторые процедуры сборки обратно в VB.NET

Теперь, есть определенная строка кода, с которой у меня возникают проблемы, при сборке предположим следующее:

EBX = F0D04080

Затем выполняется следующая строка

SHR EBX, 4

Что дает мне следующее:

EBX = 0F0D0408

Теперь в VB.NET я делаю следующее

variable = variable >> 4

Что ДОЛЖНО дать мне то же самое ... Но он отличается битом SLIGHT, вместо значения 0F0D0408 я получаю FF0D0408

Так что же здесь происходит?

Ответы [ 2 ]

4 голосов
/ 12 июля 2010

Из документации оператора >> :

При арифметическом сдвиге вправо биты, сдвинутые за крайнюю правую позицию бита, отбрасываются, а крайний левый (знаковый) бит распространяется на позиции битов, освобожденные слева. Это означает, что если шаблон имеет отрицательное значение, освободившиеся позиции устанавливаются в единицу; в противном случае они устанавливаются на ноль.

Если вы используете тип данных со знаком, F0B04080 имеет отрицательный знак (бит 1 в начале), который копируется в свободные позиции слева.

Кстати, это не что-то специфичное для VB.NET: variable >> 4 переводится в IL-инструкцию shr, которая является «арифметическим сдвигом» и, напротив, сохраняет знак к инструкции по сборке x86 SHR, которая является беззнаковым сдвигом. Для выполнения арифметического сдвига в ассемблере x86 можно использовать SAR.

Чтобы использовать беззнаковое смещение в VB.NET, вам нужно использовать беззнаковую переменную:

Dim variable As UInteger = &HF0D04080UI

Символ UI типа в конце F0D04080 сообщает VB.NET, что литерал представляет собой целое число без знака (в противном случае он будет интерпретирован как целое число со знаком минус, и в результате будет получено назначение во время компиляции).

1 голос
/ 12 июля 2010

Оператор >> VB выполняет арифметическое смещение, которое смещается в знаковый бит, а не в 0.

variable = (variable >> shift_amt) And Not (Integer.MinValue >> (shift_amt - 1))

должно дать вам эквивалентное значение, даже если оно немного длинное. В качестве альтернативы, вы можете использовать целое число без знака (UInteger или UInt32), так как для сдвига нет знака.

...