Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

умножение 4х-байтных чисел

64K
21 сентября 2011 года
az20110303
29 / / 13.09.2011
ассемблерная инмтрукция i386 mul при использовании следующим образом
mul eax, r/m32
возвращает результат в EDX:EAX, в EDX - старшую часть, в EAX - младшую.
Как в С99 получить эту старшую часть без ассемблерных вставок?
41K
21 сентября 2011 года
kisssko
108 / / 28.10.2010
Походу никак. :(
Вот какой код даёт MSVC++ 2008:

Код:
typedef unsigned   int   u32;
typedef unsigned __int64 u64;
unsigned int volatile val1;
unsigned int volatile val2;
unsigned __int64 volatile result;


int wmain(int argc, wchar_t **argv)
{
00411370 55               push        ebp  
00411371 8B EC            mov         ebp,esp
00411373 81 EC C0 00 00 00 sub         esp,0C0h
00411379 53               push        ebx  
0041137A 56               push        esi  
0041137B 57               push        edi  
0041137C 8D BD 40 FF FF FF lea         edi,[ebp-0C0h]
00411382 B9 30 00 00 00   mov         ecx,30h
00411387 B8 CC CC CC CC   mov         eax,0CCCCCCCCh
0041138C F3 AB            rep stos    dword ptr es:[edi]
    val1=0xFFFF1234;
0041138E C7 05 44 71 41 00 34 12 FF FF mov         dword ptr [val1 (417144h)],0FFFF1234h
    val2=8;
00411398 C7 05 40 71 41 00 08 00 00 00 mov         dword ptr [val2 (417140h)],8
    result=(u64)(val1*val2);
004113A2 A1 44 71 41 00   mov         eax,dword ptr [val1 (417144h)]
004113A7 8B 0D 40 71 41 00 mov         ecx,dword ptr [val2 (417140h)]
004113AD 0F AF C1         imul        eax,ecx
004113B0 33 D2            xor         edx,edx
004113B2 A3 48 71 41 00   mov         dword ptr [result (417148h)],eax
004113B7 89 15 4C 71 41 00 mov         dword ptr [result+4 (41714Ch)],edx

    return 0;
004113BD 33 C0            xor         eax,eax
}
004113BF 5F               pop         edi  
004113C0 5E               pop         esi  
004113C1 5B               pop         ebx  
004113C2 8B E5            mov         esp,ebp
004113C4 5D               pop         ebp  
004113C5 C3               ret              
--- Нет исходного файла --------------------------------------------------------


Как видно, EDX принудительно затирается.

P.S. наверное потому, что ваш вариант не кроссплатформенен, и стандартом не поддерживается.
41K
21 сентября 2011 года
kisssko
108 / / 28.10.2010
Вот, кстати, вариант с релизным профилем сборке (предыдущий собирался с дебажным).
Как видно, уже EDX не затирается, но в старшую часть всё равно пишется ноль, вместо EDX.

Код:
typedef unsigned   int   u32;
typedef unsigned __int64 u64;
unsigned int volatile val1;
unsigned int volatile val2;
unsigned __int64 volatile result;


int wmain(int argc, wchar_t **argv)
{
        val1=0xFFFF1234;
00401000 C7 05 74 33 40 00 34 12 FF FF mov         dword ptr [val1 (403374h)],0FFFF1234h
        val2=8;
0040100A C7 05 70 33 40 00 08 00 00 00 mov         dword ptr [val2 (403370h)],8
        result=(u64)(val1*val2);
00401014 A1 70 33 40 00   mov         eax,dword ptr [val2 (403370h)]
00401019 8B 0D 74 33 40 00 mov         ecx,dword ptr [val1 (403374h)]
0040101F 0F AF C1         imul        eax,ecx
00401022 A3 78 33 40 00   mov         dword ptr [result (403378h)],eax
00401027 C7 05 7C 33 40 00 00 00 00 00 mov         dword ptr [result+4 (40337Ch)],0

        return 0;
00401031 33 C0            xor         eax,eax
}
00401033 C3               ret
297
21 сентября 2011 года
koodeer
1.2K / / 02.05.2009
Можно вместо четырёхбайтовых int использовать восьмибайтовые long long. Старшую часть элементарно выделить сдвигом.
41K
22 сентября 2011 года
kisssko
108 / / 28.10.2010
Цитата: koodeer
Можно вместо четырёхбайтовых int использовать восьмибайтовые long long. Старшую часть элементарно выделить сдвигом.



Сдвигом - это более ресурсоёмко. Это ж дополнительная операция. Лучше через приведение типа. ((int*)&value64bit)[1]

64K
22 сентября 2011 года
az20110303
29 / / 13.09.2011
Цитата: koodeer
Можно вместо четырёхбайтовых int использовать восьмибайтовые long long. Старшую часть элементарно выделить сдвигом.



Спасибо! а не подскажете, как лучше выводить длинный-длинный? а то сейчас пользуюсь таким вот извратом:

Цитата:
unsigned long long a = 0x8000000000000000;
printf("%08X%08X\n",*(unsigned int*)(((char*)&a)+4), *((unsigned int*)(&a)) );

41K
22 сентября 2011 года
kisssko
108 / / 28.10.2010
Для вывода long long (aka __int64) используется макрос printf "%lld" - для чисел со знаком, и "%llu" - для чисел без знака.

Собственно: "%hhd", "%hhu" - 8 бит; "%hd", "%hu" - 16 бит, "%ld", "%lu" (или просто "%d", "%u" для 32-битных платформ) - 32 бита;
ну и "%lld", "%llu" - 64 бита.

"%hhd" и "%hhu" не работают в винде (действуют как "%hd" и "%hu" соответственно). Но можно взять сторонний исходник printf/sprintf.
Например, выдрать из стандартной линуксовой библиотеки libc.
41K
22 сентября 2011 года
kisssko
108 / / 28.10.2010
Кстати, вот такой процидуркой MSVC++ множит 64-битные числа. Так что всё ОК. :)

Цитата:
--- f:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\llmul.asm ---------------------
00411D20 8B 44 24 08 mov eax,dword ptr [esp+8]
00411D24 8B 4C 24 10 mov ecx,dword ptr [esp+10h]
00411D28 0B C8 or ecx,eax
00411D2A 8B 4C 24 0C mov ecx,dword ptr [esp+0Ch]
00411D2E 75 09 jne hard (411D39h)
00411D30 8B 44 24 04 mov eax,dword ptr [esp+4]
00411D34 F7 E1 mul eax,ecx
00411D36 C2 10 00 ret 10h
00411D39 53 push ebx
00411D3A F7 E1 mul eax,ecx
00411D3C 8B D8 mov ebx,eax
00411D3E 8B 44 24 08 mov eax,dword ptr [esp+8]
00411D42 F7 64 24 14 mul eax,dword ptr [esp+14h]
00411D46 03 D8 add ebx,eax
00411D48 8B 44 24 08 mov eax,dword ptr [esp+8]
00411D4C F7 E1 mul eax,ecx
00411D4E 03 D3 add edx,ebx
00411D50 5B pop ebx
00411D51 C2 10 00 ret 10h
--- Нет исходного файла --------------------------------------------------------



Вот, как раз тут EDX используется.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог