powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Раскидать 64 бит по 64 байтам в ASM (Delphi)
28 сообщений из 28, показаны все 2 страниц
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36406559
Изначально есть массив
array[0..63] of Byte
допустим, в каждой ячейке хранится число 3
есть переменная типа Int64, какие-то биты, которой, заполнены 1-ей, какие-то 0-м
как бы быстро раскидать эти биты по соотв. ячейкам массива (просуммировать)
чтобы получить соотв-нно 4-ки в ячейках куда попали биты с единицами
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36406572
Фотография Green2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сдвиг 1 на разряд и логическое умножение с числом...


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36406991
Vowk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я не силен в Delphi, но вот вроде бы работает правильно:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
procedure TForm1.Button2Click(Sender: TObject);
var x : Int64;
    i,j,k : integer;
    lp, ind : byte;
    ar : array[ 0 .. 63 ] of byte;
    s : string;
begin
  x:=  7 ; // переменная, биты которой заполнены
  for i:= 0  to  63  do ar[i] :=  3 ;
  lp := 1 ;
  asm
    lea edx, x
    mov ebx, 63 
@m5:
    cmp byte ptr lp, 2 
    ja @exit
    cmp byte ptr lp, 1 
    jnz @m3
    mov eax, dword ptr [edx]; // младщая часть X
    jmp @m4
@m3:
    mov eax, dword ptr [edx +  4 ]; // старшая часть X
@m4:
    mov ecx, 32 
@m6:
    jcxz @m1
    ror eax, 1 
    jnc @no_add
    add byte ptr [ ar + ebx], 1 
@no_add:
    dec ecx
    dec ebx
    jmp @m6
@m1:
    inc byte ptr lp
    jmp @m5
@exit:
    end;
  s := '';
  for i:= 0  to  63  do begin
    s := s + IntToStr(ar[i]) + ' ';
    if ((i mod  10 ) =  9 )  then s := s + chr( 10 );
    end;
  ShowMessage(s) ; // печатаем элементы массива 
end;
end.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36407354
Vowk , впечатляет - в ДВА раза быстрее, чем мой корявый вариант, при этом даже если обращаться к массиву через указатели - то же самое:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
 procedure  TForm1.Button1Click(Sender: TObject);
 var  x : Int64;
    i,j,k : integer;
    lp, ind : byte;
    ar :  packed   array [ 0 .. 63 ]  of  byte;
    s :  string ;
    n: integer;
 begin 
   for  n:= 0   to   10000000   do 
   begin 
  x:=  7 ;
   for  i:= 0   to   63   do  ar :=  3 ;
  lp := 1 ;
   asm 
    lea edx, x
    mov ebx, 63 
@m5:
    cmp byte ptr lp, 2 
    ja @exit
    cmp byte ptr lp, 1 
    jnz @m3
    mov eax, dword ptr [edx];
    jmp @m4
@m3:
    mov eax, dword ptr [edx +  4 ];
@m4:
    mov ecx, 32 
@m6:
    jcxz @m1
    ror eax, 1 
    jnc @no_add
    add byte ptr [ ar + ebx], 1 
@no_add:
    dec ecx
    dec ebx
    jmp @m6
@m1:
    inc byte ptr lp
    jmp @m5
@exit:
     end ;
   end ;

  s := '';
   for  i:= 0   to   63   do   begin 
    s := s + IntToStr(ar[i]) + ' ';
     if  ((i  mod   10 ) =  9 )   then  s := s + chr( 10 );
     end ;

  ShowMessage(s) ;  [i]// печатаем элементы массива, полученные с asm 

   // мой корвявый вариант 
   for  n:= 0   to   10000000   do 
   begin 
     for  i:= 0   to   63   do  ar :=  3 ;
     for  i:= 0   to   63   do 
      if  (x  shr  ( 63 -i))> 0   then 
       ar[i]:=ar[i]+ 1 ;
   end ;

  s := '';
   for  i:= 0   to   63   do   begin 
    s := s + IntToStr(ar[i]) + ' ';
     if  ((i  mod   10 ) =  9 )  then  s := s + chr( 10 );
     end ;
  ShowMessage(s) ;  [i]// снова печатаем элементы массива 
 end ;
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36407554
Vowk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, существенная разница в скорости. Получается, что расширение ASM в Delphi имеет определенный смысл и вполне работоспособно, а я смотрел на эту особенность как на прикол какой-то.
Возможно скорость еще можно повысить, если использовать 64-битный сдвиг, просто команду не помню. Если Delphi её поймет, то можно избавиться от одного цикла.
По поводу packed принял к сведению - важная деталь, мною упущенная :)
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36407886
VowkВозможно скорость еще можно повысить, если использовать 64-битный сдвиг, просто команду не помню
Да. Было бы интересно сравнить :)
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36407980
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vowk,

молодой человек, ну зачем же было делать такое макраме из кода? Посмотрите, у Вас же там одни переходы. Да и к тому же сканирование просто аховое, есть ведь же BSF, BTR и ADC.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408070
Vowk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mozok,
ну я сразу предупредил, что не претендую на безукоризненность :)
Спасибо за замечания, про BSF, BTR и ADC посмотрю информацию, а также подумаю над тем, как обойтись без операторов перехода.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408123
Фотография Green2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vowk> Возможно скорость еще можно повысить, если использовать 64-битный
сдвиг, просто команду не помню. Если Delphi её поймет, то можно избавиться
от одного цикла.

Эта команда набирается из нескольких команд. Сдвигается верхний 32 бит
регистр, младьший бит в флаге переноса, а потом сдвигается младьшие 32 бит,
а старший бит ставится из флага переноса.


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408160
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще вариант. Берем чуть другой алгоритм, пишем (на С, но это неважно)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	
int		ar[ 64 ]={ 0 };
	long long	x, mask;
	x = 0xfffff;
	mask =  1 ;
	for (int i =  0 ; i <  63 ; i++)
	{
		ar[i] += (x & mask) !=  0 ;
		mask <<=  1 ;
	}

Компилируем с включенной оптимизацией. Смотрим что получается и дооптимизируем руками, если получается (а тут немножко есть лишнего)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
?arrayfunc@@YAXXZ PROC					; arrayfunc, COMDAT

;  33    : {

	push	ebp
	mov	ebp, esp
	and	esp, - 8 					; fffffff8H
	sub	esp,  256 				; 00000100H
	push	esi
	push	edi

;  34    : 	int		ar[ 64 ]={ 0 };

	xor	edi, edi
	push	 252 					; 000000fcH
	lea	eax, DWORD PTR _ar$[esp+ 272 ]
	push	edi
	push	eax
	mov	DWORD PTR _ar$[esp+ 276 ], edi
	call	_memset
	add	esp,  12 					; 0000000cH

;  35    : 	long long	x, mask;
;  36    : 	x = 0xfffff;
;  37    : 	mask =  1 ;

	xor	esi, esi
	mov	ecx,  1 

;  38    : 	for (int i =  0 ; i <  63 ; i++)

	xor	edx, edx
$LL3@arrayfunc:

;  39    : 	{
;  40    : 		ar[i] += (x & mask) !=  0 ;

	mov	eax, ecx
	and	eax,  1048575 				; 000fffffH
	or	eax, edi
	je	SHORT $LN6@arrayfunc
	mov	eax,  1 
	jmp	SHORT $LN7@arrayfunc
$LN6@arrayfunc:
	xor	eax, eax
$LN7@arrayfunc:
	add	DWORD PTR _ar$[esp+edx* 4 + 264 ], eax

;  41    : 		mask <<=  1 ;

	shld	esi, ecx,  1 
	inc	edx
	add	ecx, ecx
	cmp	edx,  63 					; 0000003fH
	jl	SHORT $LL3@arrayfunc

;  42    : 	}
;  43    : }

Переносим в Дельфи.

Обратите внимание, что компилер все, что можно, засунул в регистры и используется всего одна косвенная операция. Когда пишешь сам, регистры считать ну очень неудобно, особенно на x86.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408186
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот еще пара ремарок:
1. Когда смотришь ассемблерный код, становится понятно, как поправить оригинал, чтобы скомпилилось более эффективно.
2. Когда (давно) я смотрел на код, который генерит Дельфи - отторжений не вызывало, оптимизатор был вполне на уровне.

Так что может быть и не нужно писать на ассемблере (когда нужны инструкции SIMD = MMX итп - исключение), а вот смотреть - обязательно.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408279
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vowk,
вот, набросал на досуге. Честно скажу, сам не проверял.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
  asm
    lea edi, x
    xor esi, esi
    mov ebx, 3Fh ; // 64  -  1 . Можно и  128  -  1 , и  256  -  1 , лишь бы массив позволял :)
 
@load_dword:
    mov eax, dword ptr [edi + esi]; //Загрузка очередного DWORD'a

@scan_dword:
    bsr ecx, eax
    jz @next_dword
    btr eax, ecx
    mov edx, ebx
    sub edx, ecx
    inc byte ptr [ar + edx]
    inc ecx
    loop @scan_dword

@next_dword:    
    add esi, 04h
    sub ebx, 20h
    jnc @load_dword

    end;
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408310
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mozok,

Есть вложенный цикл - уже плохо.
И похоже с ошибками.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408318
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemargl,

нет, ну так же совсем никуда не годится :). Компилятор увидел, что х помещается в DWORD и оставил обработку только младших битов. А Вы попробуйте сделать x = 0xFFFFFFFFFFFF и посмотрите, что он нагенерит.
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408334
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemargl
Есть вложенный цикл - уже плохо.

Да будет Вам, 2 цикла исключительно из-за загрузки следующего DWORD'а. Если у Вас есть более оптимальный вариант, не дублируя код, предложите. А вот переходов у меня уже на 1 меньше.
SiemarglИ похоже с ошибками.
Вполне вероятно, говорю же, по-быстрому набросал. А где именно похоже на ошибку?
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408351
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mozok,

Тут похоже на ошибку
Код: plaintext
1.
2.
    inc ecx
    loop @scan_dword

У меня все верно (вернее у С компилятора) long long == int64.
Еще под отладчиком я прогнал - проверил.

Нужен желающий погонять скорость на одной машине ))
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408370
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglMozok,

Тут похоже на ошибку
Код: plaintext
1.
2.
    inc ecx
    loop @scan_dword

Это защита на случай, если бит с номером 0 равен 1. Loop же сначала декрементит ECX, а потом уже сравнивает его с 0. Без инкремента ЕСХ стал бы равен в этом случае 2^32 - 1 вместо нуля и было бы сделано 2 лишних прыжка.
Siemargl
У меня все верно (вернее у С компилятора) long long == int64.
Еще под отладчиком я прогнал - проверил.
Нужен желающий погонять скорость на одной машине ))
Не-не-не, так не пойдет :). Вы лучше вложите-ка сгенерированный ассемблерный код для случая, когда x = 0xFFFFFFFFFFFF (или еще лучше, когда значение х задается с консоли).
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408372
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Однако да, недоглядел, что константу оптимизатор использует.

Меняем, заодно и подоптимизировал

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
void arrayfunc1(long long x)
{
	int		ar[ 64 ]={ 0 };
	long long	mask =  1 ;
	for (int i =  0 ; i <  63 ; i++)
	{
		if (x & mask) ar[i]++;
		mask <<=  1 ;
	}
}

?arrayfunc1@@YAX_J@Z PROC				; arrayfunc1, COMDAT

;  33    : {

	sub	esp,  260 				; 00000104H
	push	esi
	push	edi

;  34    : 	int		ar[ 64 ]={ 0 };

	xor	edi, edi
	push	 252 					; 000000fcH
	lea	eax, DWORD PTR _ar$[esp+ 276 ]
	push	edi
	push	eax
	mov	DWORD PTR _ar$[esp+ 280 ], edi
	call	_memset
	add	esp,  12 					; 0000000cH

;  35    : 	long long	mask =  1 ;

	mov	edx,  1 
	xor	esi, esi
	npad	 8 
$LL4@arrayfunc1:

;  36    : 	for (int i =  0 ; i <  63 ; i++)
;  37    : 	{
;  38    : 		if (x & mask) ar[i]++;

	mov	ecx, esi
	and	ecx,  255 				; 000000ffH
	mov	eax, edx
	or	eax, ecx
	je	SHORT $LN1@arrayfunc1
	inc	DWORD PTR _ar$[esp+edi* 4 + 268 ]
$LN1@arrayfunc1:

;  39    : 		mask <<=  1 ;

	shld	esi, edx,  1 
	inc	edi
	add	edx, edx
	cmp	edi,  63 					; 0000003fH
	jl	SHORT $LL4@arrayfunc1

;  40    : 	}
;  41    : }

	pop	edi
	pop	esi
	add	esp,  260 				; 00000104H
	ret	 0 
?arrayfunc1@@YAX_J@Z ENDP				; arrayfunc1
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408388
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блин, опять константу вычислил (
Все. Вызываю с параметром от random << 32 + random;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
;  35    : 	long long	mask =  1 ;
;  36    : 	for (int i =  0 ; i <  63 ; i++)

	mov	ebx, DWORD PTR _x$[esp+ 288 ]
	mov	ebp, DWORD PTR _x$[esp+ 284 ]
	add	esp,  12 					; 0000000cH
	mov	edx,  1 
	xor	esi, esi
$LL4@arrayfunc1:

;  37    : 	{
;  38    : 		if (x & mask) ar[i]++;

	mov	eax, edx
	mov	ecx, esi
	and	eax, ebp
	and	ecx, ebx
	or	eax, ecx
	je	SHORT $LN1@arrayfunc1
	inc	DWORD PTR _ar$[esp+edi* 4 + 276 ]
$LN1@arrayfunc1:

;  39    : 		mask <<=  1 ;

	shld	esi, edx,  1 
	inc	edi
	add	edx, edx
	cmp	edi,  63 					; 0000003fH
	jl	SHORT $LL4@arrayfunc1

;  40    : 	}
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408520
Siemargl2. Когда (давно) я смотрел на код, который генерит Дельфи - отторжений не вызывало, оптимизатор был вполне на уровне.
Проверял первый вариант, предложенный Vowk, в сравнении с моим извращенным на делфи:
с {$OPTIMIZATION OFF} asm 4ss, вариант на Delphi - 7ss
c {$OPTIMIZATION ON} asm 2ss, вариант на Delphi - 5ss
Грустно, что не силен в asm - даже перенести не могу в делфи толком то, что предложил Siemargl :(

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
asm
	sub	esp,  260 
	push	esi
	push	edi

	xor	edi, edi
	push	 252 
	lea	eax, ar[esp+ 276 ]
	push	edi
	push	eax
	mov	DWORD PTR ar[esp+ 280 ], edi
	//ll	_memset
	add	esp,  12 

	mov	ebx, DWORD PTR x[esp+ 288 ]
	mov	ebp, DWORD PTR x[esp+ 284 ]
	add	esp,  12 
	mov	edx,  1 
	xor	esi, esi

@LL4:
	mov	eax, edx
	mov	ecx, esi
	and	eax, ebp
	and	ecx, ebx
	or	eax, ecx
	je @LN1
	inc	DWORD PTR ar[esp+edi* 4 + 276 ]

@LN1:
	shld	esi, edx,  1 
	inc	edi
	add	edx, edx
	cmp	edi,  63 
	jl	@LL4

	pop	edi
	pop	esi
	add	esp,  260 
	ret	 0 
end;

не знаю что за
ll _memset - закоментарил ибо ругается :/
Delphi[Error] Unit1.pas(110): Undeclared identifier: 'll'
переходы с SHORT тоже не вкуривает - short убрал
Код: plaintext
inc	DWORD PTR ar[esp+edi* 4 + 276 ]
ругается:
Delphi[Error] Unit1.pas(126): Invalid register combination
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36408530
если закоментарить
Код: plaintext
inc	DWORD PTR ar[esp+edi* 4 + 276 ]
то при первом же вхождении на
Код: plaintext
mov	DWORD PTR ar[esp+ 280 ], edi
Вылетает "Ошибка чтения по адресу..."
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36409802
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Раскидыватель,

По Вашем примеру, убираем первый "add esp, 12" - он лишний.
call memset - закомментили и ладно (это вызов обнуления массива)

Можно убрать весь кусок, относящийся к обнулению, т.е.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	push	 252 
	lea	eax, ar[esp+ 276 ]
	push	edi
	push	eax
	mov	DWORD PTR ar[esp+ 280 ], edi
	//ll	_memset
	add	esp,  12  !!!! - ошибочное лишнее

	mov	ebx, DWORD PTR x[esp+ 288 ]
	mov	ebp, DWORD PTR x[esp+ 284 ]
	add	esp,  12 

Адресация там чуть другая используется. Пробуем править под синтаксис asm-delphi и без memset
Ожидаем на стеке один параметр функции типа int64

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
// _ar$ = - 256 						; size =  256 
// _x$ =  8 							; size =  8 
// ?arrayfunc1@@YAX_J@Z PROC				; arrayfunc1, COMDAT

;  33    : {

	sub	esp,  256 				; 00000100H
	push	ebx

;  34    : 	int		ar[ 64 ];//={ 0 };
;  35    : 	long long	mask =  1 ;
;  36    : 	for (int i =  0 ; i <  63 ; i++)

	mov	ebx, DWORD PTR [esp+ 260 + 8 ]
	push	ebp
	mov	ebp, DWORD PTR [esp+ 260 + 8 ]
	push	esi
	push	edi
	xor	esi, esi
	mov	edx,  1 
	xor	edi, edi
$LL4@arrayfunc1:

;  37    : 	{
;  38    : 		if (x & mask) ar[i]++;

	mov	eax, edx
	mov	ecx, esi
	and	eax, ebp
	and	ecx, ebx
	or	eax, ecx
	je	$LN1@arrayfunc1
	inc	DWORD PTR [esp+edi* 4 + 272 - 256 ]
$LN1@arrayfunc1:

;  39    : 		mask <<=  1 ;

	shld	esi, edx,  1 
	inc	edi
	add	edx, edx
	cmp	edi,  63 					; 0000003fH
	jl	$LL4@arrayfunc1

;  40    : 	}
;  41    : }

	pop	edi
	pop	esi
	pop	ebp
	pop	ebx
	add	esp,  256 
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36410231
Siemargl , что-то я растерялся малость...
Попробовал скомпилировать на другой машине с вкл/выкл оптимизацей
на ней получается, что вариант на Delphi быстрее предложенных на ASM,
правда в твой asm я не понял как обращаться к моему массиву, поэтому, конечно, это некорректно сравнивать, но все равно все три варианта если что:
Попробуй скомпилрованный экзешник запустить на машине, где при компиляции не важно с оптимизайцией или без вариант на Delphi работает медленнее.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
 procedure  TForm1.Button1Click(Sender: TObject);
 var  x : Int64;
    i: integer;
    lp : byte;
    ar :  packed   array [ 0 .. 63 ]  of  byte;
    n: integer;
    s:  String ;
 begin 
   //*****************************************************// 
   //*****************************************************// 
   // первый вариант 
   for  n:= 0   to   10000000   do 
   begin 
  x:=  7 ;
   for  i:= 0   to   63   do  ar :=  3 ;
  lp := 1 ;
   asm 
    lea edx, x
            mov ebx, 63 
        @m5:
            cmp byte ptr lp, 2 
            ja @exit
            cmp byte ptr lp, 1 
            jnz @m3
            mov eax, dword ptr [edx];
            jmp @m4
        @m3:
            mov eax, dword ptr [edx +  4 ];
        @m4:
            mov ecx, 32 
        @m6:
            jcxz @m1
            ror eax, 1 
            jnc @no_add
            add byte ptr [ ar + ebx], 1 
        @no_add:
            dec ecx
            dec ebx
            jmp @m6
        @m1:
            inc byte ptr lp
            jmp @m5
        @exit:
     end ;
   end ;

  s := '';
   for  i:= 0   to   63   do   begin 
    s := s + IntToStr(ar[i]) + ' ';
     if  ((i  mod   10 ) =  9 )   then  s := s + chr( 10 );
     end ;

  ShowMessage(s) ;  [i]// печатаем элементы массива, полученные с ASM1 

   //*****************************************************// 
   //*****************************************************// 
   // вариант на Dephi 
   for  n:= 0   to   10000000   do 
     for  i:= 0   to   63   do  ar :=  3 ;
     for  i:= 0   to   63   do 
      if  (x  shr  ( 63 -i))> 0   then 
       ar[i]:=ar[i]+ 1 ;

  s := '';
   for  i:= 0   to   63   do   begin 
    s := s + IntToStr(ar[i]) + ' ';
     if  ((i  mod   10 ) =  9 )  then  s := s + chr( 10 );
     end ;
  ShowMessage(s) ;  [i]// снова печатаем элементы массива c Delphi 

   //*****************************************************// 
   //*****************************************************// 
   // вариант ASM2 
   for  i:= 0   to   10000000   do 
   asm 
    	sub	esp,  256 
    	push	ebx
    
    	mov	ebx, DWORD PTR [esp+ 260 + 8 ]
    	push	ebp
    	mov	ebp, DWORD PTR [esp+ 260 + 8 ]
    	push	esi
    	push	edi
    	 xor 	esi, esi
    	mov	edx,  1 
    	 xor 	edi, edi
    
    @LL4:
    	mov	eax, edx
    	mov	ecx, esi
    	 and 	eax, ebp
    	 and 	ecx, ebx
    	 or 	eax, ecx
      je @LN1
    	inc	DWORD PTR [esp+edi* 4 + 272 - 256 ]
    
    @LN1:
    	shld	esi, edx,  1 
    	inc	edi
    	add	edx, edx
    	cmp	edi,  63 
    	jl	@LL4
    
    	pop	edi
    	pop	esi
    	pop	ebp
    	pop	ebx
    	add	esp,  256 
   end ;

  s := '';
   for  i:= 0   to   63   do   begin 
    s := s + IntToStr(ar) + ' ';
     if  ((i  mod   10 ) =  9 )  then  s := s + chr( 10 );
     end ;
  ShowMessage(s) ;  [i]// печатаем элементы массива c ASM2 
 end ;
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36410236
тсПопробуй скомпилрованный экзешник запустить...
хотел сказать, попробую
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36410323
Наврал. У меня ошибка в варианте Delphi потому и быстрее - я в цикле 10 млн раз просто инициализирую массив а разбивку делаю всего один раз. Сделал как надо - вариант с ASM по-прежнему миним в два раза быстрее.
Только как сделать, чтобы вариант с Siemargl работал именно с массивом ar
и именно только цикл разбивки - инициализация пусть на делфи остается для одинаковых условий сравнения первого и второго варианта ASM
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36410509
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Раскидыватель,

У нас сегодня новый год, потому без ошибок не паишу)

Изменений мало
у меня в коде начало массива DWORD PTR [esp+0*4+272-256] на момент вызова.

Задай локальную переменную фк[] массив of integer; и замени 272-256 на смещение относительно стека на момент вызова.

Есдиственное - маловато вызовов для уточнения скорости.

Всех с 1м января (по старому)!
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36410625
Siemarglна смещение относительно стека на момент вызова
Не выпив еще разок за Новый Год, фиг пойму :)
...
Рейтинг: 0 / 0
Раскидать 64 бит по 64 байтам в ASM (Delphi)
    #36413697
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inc DWORD PTR [esp+edi*4+272-256]

меняем на
inc DWORD PTR [ar+edi*4].
Дельфи смещение ar сама вычислит.

Массив INTEGER!
...
Рейтинг: 0 / 0
28 сообщений из 28, показаны все 2 страниц
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Раскидать 64 бит по 64 байтам в ASM (Delphi)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]