Переполнение сдвига влево GCC

Выберите: Стандартная библиотека Python - устойчивость данных . Какой из них наиболее подходит, может варьироваться в зависимости от ваших конкретных потребностей.

pickle , вероятно, является самым простым и наиболее способным в том, что касается «записи произвольного объекта в файл и его восстановления» - он может автоматически обрабатывать пользовательские классы и циклические ссылки.

Для лучшей производительности травления (скорость и пространство) используйте cPickle в HIGHEST_PROTOCOL.

21
задан msc 18 May 2017 в 09:58
поделиться

1 ответ

Краткий ответ: процессор Intel маскирует число сдвигов до 5 бит (максимум 31). Другими словами, фактически выполненное смещение составляет 32 & amp; 31, что равно 0 (без изменений).

Тот же результат появляется при использовании gcc на 32-битном ПК под Linux.

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

int main(){
    int y = 32;
    unsigned int z = 1 << y;
    unsigned int k = 1;
    k <<= y;
    printf("z: %u, k: %u\n", z, k);
}

.. используя команду gcc -Wall -o a.s -S deleteme.c (комментарии мои)

main:
leal    4(%esp), %ecx
andl    $-16, %esp
pushl   -4(%ecx)
pushl   %ebp
movl    %esp, %ebp
pushl   %ecx
subl    $36, %esp
movl    $32, -16(%ebp)  ; y = 32
movl    -16(%ebp), %ecx ; 32 in CX register
movl    $1, %eax        ; AX = 1
sall    %cl, %eax       ; AX <<= 32(32)
movl    %eax, -12(%ebp) ; z = AX
movl    $1, -8(%ebp)    ; k = 1
movl    -16(%ebp), %ecx ; CX = y = 32
sall    %cl, -8(%ebp)   ; k <<= CX(32)
movl    -8(%ebp), %eax  ; AX = k
movl    %eax, 8(%esp)
movl    -12(%ebp), %eax
movl    %eax, 4(%esp)
movl    $.LC0, (%esp)
call    printf
addl    $36, %esp
popl    %ecx
popl    %ebp
leal    -4(%ecx), %esp
ret

Хорошо, так что это значит? Именно эта инструкция озадачивает меня:

sall    %cl, -8(%ebp)   ; k <<= CX(32)

Очевидно, что k смещается влево на 32 бита.

Вы получили меня - оно использует инструкцию sall, которая представляет собой арифметическое смещение . Я не знаю, почему поворот на 32 приводит к повторному появлению бита в исходном положении. Моя первоначальная гипотеза состояла бы в том, что процессор оптимизирован для выполнения этой инструкции за один такт - это означает, что любой сдвиг более чем на 31 будет рассматриваться как неважно. Но мне любопытно найти ответ на этот вопрос, потому что я ожидаю, что вращение должно привести к тому, что все биты будут падать с левого конца типа данных.

Я нашел ссылку на http://faydoc.tripod.com/cpu/sal.htm , которая объясняет, что счетчик сдвига (в регистре CL) маскируется до 5 битов. Это означает, что если вы попытаетесь сдвинуться на 32 бита, фактическое выполненное смещение будет равным нулю (т.е. без изменений). Вот ответ!

17
ответ дан 29 November 2019 в 20:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: