Имитация инструкций SHL и SHR ASM в Python - PullRequest
0 голосов
/ 11 декабря 2018

В x86_64 ASM следующие инструкции выполняют битовое смещение влево и вправо соответственно.

SHL rax, cl
SHR rax, cl

Я хотел бы смоделировать эти инструкции в Python.

Для значения, такого как: 0x613025F862Я могу сделать следующее:

result = 0x613025F862 << 0x10

Однако для больших значений я получаю другой результат:

0x60018DDDBD500063 << 0x10

Это дает мне результат как: 0x60018dddbd5000630000.Однако в ASM результат будет следующим: 0x8dddbd5000630000

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

(0x60018DDDBD500063 << 0x10) & 0xffffffffffffffff

Теперь, как я могу написать эффективную универсальную функцию, котораядает правильный результат?

Для этой цели я написал функцию, показанную ниже:

def shift_left(input):
    result = input << 0x10
    if result > 0xffffffffffffffff:
        result = result & 0xffffffffffffffff
    else:
        result = result

    return result

Спасибо.

1 Ответ

0 голосов
/ 11 декабря 2018

Для сдвигов с переменным числом не забывайте также маскировать число сдвигов.shl / shr смотрите только младшие биты cl.То же самое для bts reg,reg или reg,imm и для BMI2 shlx r64, r64/m64, r64.

Либо cl & 0x3f для 64-битных смен, либо cl & 0x1f для 32, 16 или 8-битных смен.(Таким образом, 16- и 8-битные сдвиги могут обнулять 8- или 16-битный регистр, сдвигая все биты).См. Раздел «Эксплуатация» руководства для псевдокода: http://felixcloutier.com/x86/SAL:SAR:SHL:SHR.html


Вам не нужно делать условное маскирование

result = (input << 0x10) & 0xffffffffffffffff

  or 
result = (input << (cl & 0x3f)) & 0xffffffffffffffff

Python2 имеетЦелочисленный тип фиксированной ширины, который неявно отбрасывает старшие биты для вас, но Python3 этого не делает.

Для сдвига вправо вам, вероятно, не нужно маскировать, предполагая, что целочисленные типы Python не превращаются в плавающиеточка или фиксированная точка при сдвиге вправо.


Я также не уверен, как Python обрабатывает целые числа со знаком: shr сдвигает нули, а sar сдвигает копии бит знака. В x86 asm -1 и 0xffffffffffffffff буквально одно и то же (все биты установлены) , поэтому в Python вы можете найти, что вам нужно нормализовать ввод для shr, чтобы он был беззнаковым в *Диапазон 1032 *, или для sar нормализуйте вход для подписи в диапазоне -2^63 .. +2^63-1.

Сдвиг влево может «переполниться» и установить старший бит результата.Любые инструкции, которые смотрят на значение с подписанной интерпретацией, будут видеть его как отрицательный.(например, sar, расширение с одним операндом imul ecx или test / cmp / другие инструкции, которые устанавливают SF и OF.)

И, конечно, 32, 16или 8-битный регистр, старший бит этого регистра - бит знака.

...