· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› Алгоритм Евклида

. 1 . 2 . 3 . >>

Посл.отвђт Сообщенiе


Дата: Авг 16, 2004 21:08:34

Гм, на С пишется просто:
/* a must be >= b */
unsigned gcd(unsigned a, unsigned b)
{
	while(b)
	{
		unsigned r = a % b;
		a = b;
		b = r;
	}

	return a;
}


Компилятор в режиме самой офуительной оптимизации выдал мне сие:
; _a$ = eax
; _b$ = ecx

; 8    : 	while(b)

	test	ecx, ecx
	je	SHORT $L8421
$L8420:

; 9    : 	{
; 10   : 		unsigned r = a % b;

	xor	edx, edx
	div	ecx

; 11   : 		a = b;

	mov	eax, ecx
	test	edx, edx

; 12   : 		b = r;

	mov	ecx, edx
	jne	SHORT $L8420
$L8421:


Как по мне, так в test edx, edx/jne SHORT $L8420 нужды нет. Можно было бы просто заменить это jmp. Плоды моих усилий вымучались в:
unsigned gcd(unsigned a, unsigned b)
{
	unsigned r = 0;

	__asm
	{
		mov eax, a
		mov ecx, b
again:
		test ecx, ecx
		je	SHORT end
		xor	edx, edx
		div	ecx
		mov	eax, ecx
		mov	ecx, edx
		jmp SHORT again
end:
		mov r, eax
	}

	return r;

}


Теперь, собственно, упражнение - максимально оптимизировать скорость. Как по мне, так уже больше некуда, но, может, я ошибаюсь?


Дата: Авг 16, 2004 21:42:27

imho, вот так будет быстрее:
__declspec(naked)
unsigned int __fastcall gcd(unsigned int a, unsigned int b)
{
	__asm
	{
		mov eax, ecx
	 l1:
		cmp eax, edx
		jae l2
		xchg eax, edx
	 l2:
		sub eax, edx
		jnz l1
		retn
	}
}


Дата: Авг 16, 2004 21:46:54

Может и быстрее, но алгоритм не работает :(
И первая же инструкция мне не понравилась - ты перетираешь значение а!


Дата: Авг 16, 2004 21:56:01

прошу прощения, не протестил :)

Вот так у меня вроде работает:

__declspec(naked)
unsigned int __fastcall gcd(unsigned int a, unsigned int b)
{
	__asm
	{
		xchg eax, ecx
	 l1:
		cmp edx, eax
		jae l2
		xchg edx, eax
	 l2:
		sub edx, eax
		jnz l1
		retn
	}
}


Дата: Авг 16, 2004 22:28:18

Проверил для 777 и 629, получается 37.
Медоленные команды не используются.
		mov eax, a
		mov ecx, b

@@:		mov edx, eax
		sub eax, ecx
		jnc @b

		mov eax, ecx
		mov ecx, edx
		jnz @b

		mov r, eax


Дата: Авг 16, 2004 22:51:26

S_T_A_S_

Два вопроса.
1) Чей алгоритм быстрее? Твой или green'a?
2) Что это за метка "@@"? И где метка "@b"? Ты пользуешься синтаксисом, которого я не знаю :(


Дата: Авг 16, 2004 23:17:07

Сам алгоритм вроде одинаковый, заменили деление вычитанием.

У меня не используется xchg, которая довольно медленна и не спаривается с другими командами.
Одна команда проверки условия вместо 2х.
Нет зависимости по данным, кроме как jnc сразу после sub (зато jnz должен быть предсказан одновременно с jnc).


"@@" - это просто анонимная локальная метка, "@b" - значит переход на ближайшую "@@" назад (если "@f" - это вперёд).
Я и забыл, что С регается на символы @ :-)


Дата: Авг 16, 2004 23:22:37

volodya
> 2) Что это за метка "@@"? И где метка "@b"? Ты пользуешься синтаксисом, которого я не знаю :(

jmp @B или jmp @b - это прыжок назад на ближайшую метку @@:
jmp @F или jmp @f - тоже самое, но вперед ;-)

ЗЫ: нормальный ассемблерный синтаксис.


Дата: Авг 16, 2004 23:23:33

Пока писал в оффлайне S_T_A_S_ меня уже опередил ;-)


Дата: Авг 16, 2004 23:31:49

Все, понял. Всем спасибо :)


Дата: Авг 16, 2004 23:48:34

S_T_A_S_

Твой алгоритм вычисляет наибольший общий делитель, но зацикливается после его нахождения. Вот так работает, правда две команды плюс:
    mov eax, 10557
    mov ecx, 1530

@@: cmp eax,ecx
    je short Exit
    mov edx, eax
    sub eax, ecx
    jnc @B

    mov eax, ecx
    mov ecx, edx
    jnz @B 
Exit:


Дата: Авг 17, 2004 00:01:46

cresta

Мог бы и добавить, что ответ в eax :|>

А от
@@: cmp eax,ecx
    je short Exit

избавиться нельзя? Мне не нравится.


Дата: Авг 17, 2004 00:15:41

Ой млин.. точно, спасибо :)
косячный вариант запостил :(

Правильно так:
		mov eax, a
		mov ecx, b

@@:		mov edx, eax
		sub eax, ecx
		ja  @b

		mov eax, ecx
		mov ecx, edx
		jnz @b

		mov r, eax


Дата: Авг 17, 2004 00:20:22

А алгоритм green'a для некоторых пар чисел выдаёт ошибочный результат. Я так понял, это зависит от содержимого edx. Если его обнулить перед циклом, то вообще зацикливается. Нельзя ли уточнить, что должно быть в регистре edx перед выполнением цикла?


Дата: Авг 17, 2004 00:21:33

а вот так алгоритм S_T_A_S_
можно в С-код впаять:
__declspec(naked)
unsigned int __fastcall gcd(unsigned int a, unsigned int b)
{
	__asm
	{
	l:
			mov eax, edx
			sub edx, ecx
			ja l

			mov edx, ecx
			mov ecx, eax
			jnz l
			ret
	}
}

. 1 . 2 . 3 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.082