1

Тема: CMD/BAT: Эмуляция 64-битного числа

Здесь приведены арифметические/логические операции для 64-битного числа
64-битное число задается как binary64_(Название)_l и binary64_(Название)_h
_l и _h определяет нижние и верхние части 64-битного числа


:div
rem Деление 64-битного числа
if !binary64_%2_l!==0 if !binary64_%2_h!==0 (
	Echo Division by zero
	goto :eof
)
set binary64_%3_l=0
set binary64_%3_h=0
Call :getLastBitPos %2 posB
Call :copy tmp03 %1
Call :load32 tmp04 0
for /l %%i in (63,-1,0) do (
	set /a "hpos=posB + %%i"
	if !hpos! lss 64 (
		Call :copy tmp01 %2
		Call :left tmp01 %%i tmp02
		Call :copy tmp01 tmp02
		Call :compare tmp03 tmp01
		set j=false
		if !stat!==E set j=true
		if !stat!==G set j=true
		if !j!==true (
			Call :load32 tmp05 1
			Call :left tmp05 %%i tmp02
			Call :copy tmp05 tmp02
			Call :add tmp05 tmp04 tmp02
			Call :copy tmp04 tmp02
			Call :copy tmp06 %2
			Call :left tmp06 %%i tmp02
			Call :copy tmp06 tmp02
			Call :not tmp03 tmp03
			Call :add tmp03 tmp06 tmp02
			Call :not tmp02 tmp02
			Call :copy tmp03 tmp02
		)
		
	)
)
Call :copy %3 tmp04
goto :eof

:sub
rem Вычитание 64-битного числа
Call :copy tmp01 %1
Call :not tmp01 tmp01
Call :add tmp01 %2 tmp02
Call :copy tmp01 tmp02
Call :copy %3 tmp02
goto :eof

:load32
set binary64_%1_h=0
set binary64_%1_l=%2
goto :eof

:compare
rem Сравнение 64-битного числа
set stat=E
set /a "tmp01=(binary64_%1_l & 0xFFFF) - (binary64_%2_l & 0xFFFF)"
set /a "tmp02=((binary64_%1_l >> 16) & 0xFFFF) - ((binary64_%2_l >> 16) & 0xFFFF)"
set /a "tmp03=(binary64_%1_h & 0xFFFF) - (binary64_%2_h & 0xFFFF)"
set /a "tmp04=((binary64_%1_h >> 16) & 0xFFFF) - ((binary64_%2_h >> 16) & 0xFFFF)"
for /l %%i in (4,-1,1) do (
	if !stat!==E (
		if !tmp0%%i! gtr 0 (set stat=G) else if !tmp0%%i! lss 0 (set stat=L)
	)
)
goto :eof

:getLastBitPos
set tmp01=0
for /l %%i in (63,-1,0) do (
	if !tmp01!==0 (
		set /a "tmp02=%%i"
		if !tmp02! geq 32 (
			set /a tmp02-=32
			set /a "tmp03=(binary64_%1_h >> tmp02) & 1"
		) else (
			set /a "tmp03=(binary64_%1_l >> tmp02) & 1"
		)
		if !tmp03!==1 (
			set tmp01=1
			set %2=%%i
		)
	)
)
goto :eof

:copy
rem Копирование 64-битного числа
set binary64_%1_h=!binary64_%2_h!
set binary64_%1_l=!binary64_%2_l!
goto :eof

:mul
rem Умножение 64-битного числа
set /a "tmp01=binary64_%1_l & 0xFFFF"
set /a "tmp02=(binary64_%1_l >> 16) & 0xFFFF"
set /a "tmp03=binary64_%1_h & 0xFFFF"
set /a "tmp04=(binary64_%1_h >> 16) & 0xFFFF"
set /a "tmp05=binary64_%2_l & 0xFFFF"
set /a "tmp06=(binary64_%2_l >> 16) & 0xFFFF"
set /a "tmp07=binary64_%2_h & 0xFFFF"
set /a "tmp08=(binary64_%2_h >> 16) & 0xFFFF"
set /a "tmp09=(tmp01 * tmp05) & 0xFFFF"
set /a "tmp10=(((tmp09 >> 16) & 0xFFFF) + (tmp02 * tmp05)) & 0xFFFF"
set /a "tmp11=(((tmp10 >> 16) & 0xFFFF) + (tmp03 * tmp05)) & 0xFFFF"
set /a "tmp12=(((tmp11 >> 16) & 0xFFFF) + (tmp04 * tmp05)) & 0xFFFF"
set /a "tmp13=(tmp01 * tmp06) & 0xFFFF"
set /a "tmp14=(((tmp13 >> 16) & 0xFFFF) + (tmp02 * tmp06)) & 0xFFFF"
set /a "tmp15=(((tmp14 >> 16) & 0xFFFF) + (tmp03 * tmp06)) & 0xFFFF"
set /a "tmp17=(tmp01 * tmp07) & 0xFFFF"
set /a "tmp18=(((tmp17 >> 16) & 0xFFFF) + (tmp02 * tmp07)) & 0xFFFF"
set /a "tmp21=(tmp01 * tmp08) & 0xFFFF"
set /a "tmp25=tmp09"
set /a "tmp26=tmp10 + tmp13 + (((tmp01 * tmp05) >> 16) & 0xFFFF)"
set /a "tmp27=tmp11 + tmp14 + tmp17 + (((tmp02 * tmp05) >> 16) & 0xFFFF) + (((tmp01 * tmp06) >> 16) & 0xFFFF) + ((tmp26 >> 16) & 0xFFFF)"
set /a "prevBits=((tmp27 >> 16) & 0xFFFF)"
set /a "highSum11=(((tmp03 * tmp05) >> 16) & 0xFFFF)"
set /a "highSum14=(((tmp02 * tmp06) >> 16) & 0xFFFF)"
set /a "highSum17=(((tmp01 * tmp07) >> 16) & 0xFFFF)"
set /a "tmp28=tmp12 + tmp15 + tmp18 + tmp21 + prevBits + highSum11 + highSum14 + highSum17"
set /a "binary64_%3_l=(tmp25 & 0xFFFF) | ((tmp26 & 0xFFFF) << 16)"
set /a "binary64_%3_h=(tmp27 & 0xFFFF) | ((tmp28 & 0xFFFF) << 16)"
goto :eof

:add
rem Сложение 64-битного числа
set /a "tmp1=(binary64_%1_l & 0xFFFF) + (binary64_%2_l & 0xFFFF)"
set /a "tmp2=((binary64_%1_l >> 16) & 0xFFFF) + ((binary64_%2_l >> 16) & 0xFFFF)"
set /a "tmp3=(binary64_%1_h & 0xFFFF) + (binary64_%2_h & 0xFFFF)"
set /a "tmp4=((binary64_%1_h >> 16) & 0xFFFF) + ((binary64_%2_h >> 16) & 0xFFFF)"
set /a "binary64_%3_l=tmp1 + (tmp2 << 16)"
set /a "binary64_%3_h=(((tmp1 >> 16) + tmp2) >> 16) + tmp3 + (tmp4 << 16)"
goto :eof

:right
rem Беззнаковый сдвиг вправо 64-битного числа
set /a diff=%2-32
if !diff! gtr 0 (
	set /a "binary64_%3_h=0"
	set /a "binary64_%3_l=((binary64_%1_h >> (%2-32)) & ((1<<(32-(%2-32)))-1))"
) else (
	set /a "binary64_%3_h=(binary64_%1_h >> %2) & ((1<<(32-%2))-1)"
	set /a "binary64_%3_l=((binary64_%1_l >> %2) & ((1<<(32-%2))-1))|(binary64_%1_h << (32-%2))"
)
goto :eof

:left
rem Сдвиг влево 64-битного числа
set /a diff=%2-32
if !diff! gtr 0 (
	set /a "binary64_%3_h=(binary64_%1_l << (%2-32))"
) else (
	set /a "binary64_%3_h=(binary64_%1_h << %2) | ((binary64_%1_l >> (32-%2)) & ((1<<%2)-1))"
)
set /a "binary64_%3_l=binary64_%1_l << %2"
goto :eof

:xor
rem Логическое исключающее или 64-битного числа
set /a "binary64_%3_h=binary64_%1_h ^ binary64_%2_h"
set /a "binary64_%3_l=binary64_%1_l ^ binary64_%2_l"
goto :eof

:and
rem Логическое и 64-битного числа
set /a "binary64_%3_h=binary64_%1_h & binary64_%2_h"
set /a "binary64_%3_l=binary64_%1_l & binary64_%2_l"
goto :eof

:or
rem Логическое или 64-битного числа
set /a "binary64_%3_h=binary64_%1_h | binary64_%2_h"
set /a "binary64_%3_l=binary64_%1_l | binary64_%2_l"
goto :eof

:not
rem Побитовая инверсия 64-битного числа
set /a "binary64_%2_h=~binary64_%1_h"
set /a "binary64_%2_l=~binary64_%1_l"
goto :eof