64 bitowe przesunięcie bitowe

0

Jak wykonać 64 bitowe przesunięcie bitowe (<<, >> lub w przypadku np.Pascala: shl, shr) w Assemblerze na architekturze x86?
Przykładowo FPC generuje taki kod:

; Temps allocated between esp+0 and esp+4
; [pas.pas]
; [5] Begin
		sub	esp,4
; Var A located in register eax
; Var B located in register ecx
; Var C located in register eax
		mov	dword ptr [esp],ebx
		call	FPC_INITIALIZEUNITS
		mov	eax,0
		mov	edx,0
		mov	ecx,0
		mov	ebx,0
		mov	ebx,0
		mov	ebx,0
; [6] C := A << B;
		cmp	ecx,64
		jl	@@j5
		mov	eax,0
		mov	edx,0
		jmp	@@j7
@@j5:
		cmp	ecx,32
		jl	@@j6
		sub	ecx,32
		shl	eax,cl
		mov	edx,eax
		mov	eax,0
		jmp	@@j7
@@j6:
		shld	edx,eax,cl
		shl	eax,cl
@@j7:
; [7] End.
		call	FPC_DO_EXIT
		mov	ebx,dword ptr [esp]
		add	esp,4
		ret

(gdzie A, B oraz C to Int64)

Lecz niezbyt wiem, co tutaj się dzieje i dlaczego jest akurat tak, a nie inaczej (tzn.zaczynam powoli rozumieć jak to działa, lecz zanim dojdę do rozwiązania, to minie sporo czasu) :P
Szukałem w internecie, lecz nic konkretnego nie odnalazłem, a akurat tego potrzebuję :c

1

Rozumiem, że na wejściu A, B i C zawierają co najwyżej 32-bitowe wartości (inaczej by się nie kleiło).

Z kodu wynika, że wynik jest w edx:eax (tzn wyższe bity w edx, niższe w eax). ecx przechowuje wielkość przesunięcia.

Kod można przetłumaczyć na:

if (ecx >= 64) {
  eax = edx = 0; // uwaga: na x86 przy instrukcjach typu shl eax, cl nie jest brany cała wartość cl, tylko jej najniższe 5 bitów
} else if (ecx >= 32) {
  edx = A << (ecx -32)
  eax = 0
} else {
  shld edx,eax,cl // ta instrukcja przesuwa wyższy rejestr, nowe bity będą pochodzić z niższego rejestru
  shl eax,cl // ta instrukcja przesuwa niższy rejestr, nowe bity będą zerami
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1