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
--- Нет исходного файла --------------------------------------------------------
умножение 4х-байтных чисел
mul eax, r/m32
возвращает результат в EDX:EAX, в EDX - старшую часть, в EAX - младшую.
Как в С99 получить эту старшую часть без ассемблерных вставок?
Вот какой код даёт MSVC++ 2008:
Код:
Как видно, EDX принудительно затирается.
P.S. наверное потому, что ваш вариант не кроссплатформенен, и стандартом не поддерживается.
Как видно, уже 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
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
Можно вместо четырёхбайтовых int использовать восьмибайтовые long long. Старшую часть элементарно выделить сдвигом.
Цитата: koodeer
Можно вместо четырёхбайтовых int использовать восьмибайтовые long long. Старшую часть элементарно выделить сдвигом.
Сдвигом - это более ресурсоёмко. Это ж дополнительная операция. Лучше через приведение типа. ((int*)&value64bit)[1]
Цитата: koodeer
Можно вместо четырёхбайтовых int использовать восьмибайтовые long long. Старшую часть элементарно выделить сдвигом.
Спасибо! а не подскажете, как лучше выводить длинный-длинный? а то сейчас пользуюсь таким вот извратом:
Цитата:
unsigned long long a = 0x8000000000000000;
printf("%08X%08X\n",*(unsigned int*)(((char*)&a)+4), *((unsigned int*)(&a)) );
printf("%08X%08X\n",*(unsigned int*)(((char*)&a)+4), *((unsigned int*)(&a)) );
Собственно: "%hhd", "%hhu" - 8 бит; "%hd", "%hu" - 16 бит, "%ld", "%lu" (или просто "%d", "%u" для 32-битных платформ) - 32 бита;
ну и "%lld", "%llu" - 64 бита.
"%hhd" и "%hhu" не работают в винде (действуют как "%hd" и "%hu" соответственно). Но можно взять сторонний исходник printf/sprintf.
Например, выдрать из стандартной линуксовой библиотеки libc.
Цитата:
--- 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
--- Нет исходного файла --------------------------------------------------------
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 используется.