Qubc
@Qubc
Ненавижу полисемию.

Почему выражение (-1ll) в ассемблерном коде MSVC равно ff ff ff ff?

int main ( int argc, char* argv[] ) {
    auto a1 = -1LL; // msvc 17.3.5: 8 bytes
    return 0;
}

msvc / Go to disassembly:
auto a1 = -1LL;//8 bytes
00007FF725FE1773 48 C7 45 08 FF FF FF FF mov         qword ptr [a1],0FFFFFFFFFFFFFFFFh


msvc / Assembly output:
; 19   :     auto a1 = -1LL;//8 bytes

  00023	48 c7 45 08 ff
	ff ff ff	 mov	 QWORD PTR a1$[rbp], -1


Почему в машинной команде всего 4 байта, когда в ассемблерной команде все 8 байтов? В чем уловка?
  • Вопрос задан
  • 293 просмотра
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Уловка в системе процессорных комманд: 48 c7 45 08 - позволяет загрузить в 64-битную ячейку памяти 32 битное число, автоматически расширяя его до 64 бит.

Смотрите список кодов x64:
0x48 - означает, что следующая комманда работает с 64-битами.
0xC7 - mov immediate (данные в команде)
Дальше идут флаги, указывающие как интерпретировать аргументы, что куда адресовывать и т.д.

Но важно, что команда C7 работает с r/m16/32/64 данными, а аргумент у нее может быть только imm16/32 (третий столбец). Т.е. она принимает или 2 или 4 байта, в зависимости от обвеса, а записывать может до 64 бит. Сравните это с коммандой 0xB8 в той же таблице, она уже может принимать 64 бита.

Если аргумент меньше ячейки памяти, то он расширяется (sign extended) до нужного размера (бит знака копируется влево до упора). Это позволяет записать числено равное значение в более битную ячейку. ведь 32-битное число 0xFFFFFFFF - это -1 в дополнительном бинарном коде, а 0xFFFFFFFFFFFFFFFF - это тоже -1 в дополнительном 64-битном коде.

Компилятор использует вот эту команду, а не 0xB8, потому что сама команда короче, а исполняется так же быстро. Меньше кода, больше всего помещается в кеш и все работает быстрее, да и exe-шник меньше получается.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы