unsigned int* a_shl, unsigned int* a_shr
- это указатели на unsigned int
, 32-битный тип (dword).
У вас есть два хранилища qword, mov [rsi], rax
и mov [rdx], rax
, которые хранятся за пределами указанного -в объектах.
Эквивалентом C будет функция, которая принимает unsigned int*
аргументов и
*(unsigned long)a_shr = a>>count;
. Это, конечно, UB, и такое поведение (перезапись других переменных) вполне соответствует ожидаемому.
Предположительно, вы скомпилировали с отключенной оптимизацией, поэтому вызывающая сторона фактически перезагрузила a
из стека , И он поместил a_shr
или a_shl
рядом с a
в кадре стека, и один из ваших магазинов обнулел копию вашего вызывающего абонента a
.
(как обычно, g cc произошло обнуление старших 32 битов RDI, в то время как a
было помещено в EDI в качестве первого аргумента. Запись нулевого 32-битного регистра - это расширение до полного регистра. Так что ваша другая ошибка: правый перенос большого мусора в младшие 32 бита для a_shr
, не укусили вас этим абонентом.)
Более простая реализация:
global IntegerShift ; why the trailing underscore? That's weird for no reason.
IntegerShift:
;prologue not needed, we don't even use the stack
; so don't waste instructions making a frame pointer.
mov eax, edi
shl rax, cl ; a<<count
mov [rsi], eax ; 32-bit store
;mov rax, rdi ; we can just destroy our local a, we're done with it
shr edi, cl ; a>>count
mov [rdx], edi ; 32-bit store
xor eax, eax ; return 0
ret
xor eax, eax
- это самый эффективный способ обнуления 64- битовый регистр (без потраченного префикса REX). И ваше возвращаемое значение в любом случае только 32-битное, потому что вы объявили его int
, поэтому нет смысла использовать 64-битные регистры.
Кстати, если у вас был доступен BMI2 (чего вы не делаете на вашем бюджетном процессоре Pentium, к сожалению), вы можете избежать копирования всех регистров и быть более эффективными на процессорах Intel (SHL / RX составляет всего 1 моп вместо 3 для shl/r reg, cl
из-за устаревшей семантики x86 FLAGS без изменений для cl = 0 кейс)
shlx eax, edi, ecx
shrx edi, edi, ecx
mov [rsi], eax
mov [rdx], edi
xor eax, eax
ret