Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Умножение в ASM для x64-сборки / 11 сообщений из 11, страница 1 из 1
15.12.2015, 19:29
    #39129089
kopiev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
Всем добрый день,

не подскажите, как изменить код:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
// Multiply big integers:
function __Mul(a, b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD
asm
 {$IFDEF WIN64}
  // ???
 {$ELSE}
  mul edx
  mov [ecx],edx
 {$ENDIF}
end;


чтобы он не выдавал ошибки в случае x64-сборки (First chance exception at $0000000000431B82. Exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'.)

ЗС
...
Рейтинг: 0 / 0
15.12.2015, 19:40
    #39129103
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
И при чем тут умножение ?
...
Рейтинг: 0 / 0
15.12.2015, 19:42
    #39129105
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
И я бы даже спросил "и причем тут asm?"
Дабы приведенный код явно не ассемблер, а скорее что-то паскале-подобное.
...
Рейтинг: 0 / 0
15.12.2015, 20:06
    #39129119
kopiev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
Возможно, могу добавить только, что проблема в строке mov [ecx],edx , само умножение mul edx по крайней мере не выдает исключения. Директивы компилятора просто забыл удалить, извиняюсь.
...
Рейтинг: 0 / 0
15.12.2015, 20:16
    #39129132
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
Я добрый:

Тынц
http://docwiki.embarcadero.com/RADStudio/Seattle/en/Procedures_and_Functions#Calling_Conventions

Тынц
http://docwiki.embarcadero.com/RADStudio/Seattle/en/Using_Inline_Assembly_Code

32-bit

In general, the rules of register use in an asm statement are the same as those of an external procedure or function. An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers, but can freely modify the EAX, ECX, and EDX registers. On entry to an asm statement, EBP points to the current stack frame and ESP points to the top of the stack. Except for ESP and EBP, an asm statement can assume nothing about register contents on entry to the statement.

64-bit

In line with the x64 Application Binary Interface (ABI), the contents of the following registers must be preserved and restored within inline assembly functions: R12, R13, R14, R15, RDI, RSI, RBX, RBP, RSP, XMM4, XMM5, XMM6, XMM7, XMM8, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, and XMM15.

The first four parameters to inline assembler functions are passed via RCX, RDX, R8, and R9 respectively, except for floating-point arguments which use XMMO, XMM1, XMM2, XMM3. The math coprocessor is not normally used from x64 code. Registers used for function parameters can be modified freely.
...
Рейтинг: 0 / 0
15.12.2015, 20:21
    #39129135
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
kopievВозможно, могу добавить только, что проблема в строке mov [ecx],edx , само умножение mul edx по крайней мере не выдает исключения. Директивы компилятора просто забыл удалить, извиняюсь.

Правильный ответ заключается в двух словах "calling_conventions". Что это такое - ты должен знать.

Выданных мною ссылок достаточно?

Не понимаю, какой смысл в такой сложной конструкции. Чем просто a*b не подошло? Да и я бы сказал, писать in line assembler и явно не указать calling_conventions это на мой взгляд дурной тон. Я сильно тупил, когда такой код увидел без явного указания register calling conventions ))). Я конечно понимаю, что он по умолчанию такой, но вдруг кто умолчания в компиляторе изменит... и все... в общем, дурной тон IMHO
...
Рейтинг: 0 / 0
15.12.2015, 22:58
    #39129236
kopiev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
Написал такую вещь:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function __Mul(a, b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD
{$IFDEF WIN64}
 var
  aux_hi, aux_lo : UInt64;
 begin
  aux_lo := UInt64(a) * UInt64(b);
  aux_hi := aux_lo shr 32;
  aux_lo := aux_lo - aux_hi shl 32;
  HiDWORD := DWORD(aux_hi);
  Result := DWORD(aux_lo);
{$ELSE}
 asm
  mul edx
  mov [ecx],edx
{$ENDIF}
end;


Конечно не гениально, но работает. Дизассемблирование не помогло, для этой же функции, например (х64):
Код: pascal
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.
myproject.pas.61: begin
0000000000431B80 55               push rbp
0000000000431B81 4883EC20         sub rsp,$20
0000000000431B85 488BEC           mov rbp,rsp
0000000000431B88 894D30           mov [rbp+$30],ecx
0000000000431B8B 895538           mov [rbp+$38],edx
0000000000431B8E 4C894540         mov [rbp+$40],r8
myproject.pas.62: aux_lo := UInt64(a) * UInt64(b);
0000000000431B92 8B4530           mov eax,[rbp+$30]
0000000000431B95 8B4D38           mov ecx,[rbp+$38]
0000000000431B98 480FAFC1         imul rax,rcx
0000000000431B9C 48894508         mov [rbp+$08],rax
myproject.pas.63: aux_hi := aux_lo shr 32;
0000000000431BA0 488B4508         mov rax,[rbp+$08]
0000000000431BA4 48C1E820         shr rax,$20
0000000000431BA8 48894510         mov [rbp+$10],rax
myproject.pas.64: aux_lo := aux_lo - aux_hi shl 32;
0000000000431BAC 488B4510         mov rax,[rbp+$10]
0000000000431BB0 48C1E020         shl rax,$20
0000000000431BB4 48294508         sub [rbp+$08],rax
myproject.pas.65: HiDWORD := DWORD(aux_hi);
0000000000431BB8 488B4540         mov rax,[rbp+$40]
0000000000431BBC 8B4D10           mov ecx,[rbp+$10]
0000000000431BBF 8908             mov [rax],ecx
myproject.pas.66: Result := DWORD(aux_lo);
0000000000431BC1 8B4508           mov eax,[rbp+$08]
0000000000431BC4 89451C           mov [rbp+$1c],eax
myproject.pas.76: end;
0000000000431BC7 8B451C           mov eax,[rbp+$1c]
0000000000431BCA 488D6520         lea rsp,[rbp+$20]
0000000000431BCE 5D               pop rbp
0000000000431BCF C3               ret
...
Рейтинг: 0 / 0
16.12.2015, 02:04
    #39129294
kopiev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
Исключение происходило внутри функции, то есть возможно, что все дело в других регистрах в случае х64 после mul :
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function __Mul(a, b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD
asm
{$IFDEF WIN64}
  mul eax
  mov [???],eax
{$ELSE}
  mul edx
  mov [ecx],edx
{$ENDIF}
end;
...
Рейтинг: 0 / 0
16.12.2015, 07:06
    #39129316
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
kopiev,

тебе же уже Leonid Kudryavtsev сказал ответ
копай "calling_conventions", в win64 она всего одна должна применяться,
PS: а вообще регистр адреса 64-битный, это rcx
...
Рейтинг: 0 / 0
16.12.2015, 12:55
    #39129650
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
kealon(Ruslan),
Я уже ссылку дал и под спойлер текст для 64 bit загнал. Адрес (третий параметр) у него должен быть в r8. Это так же и из ассемблерного кода видно.

kopiev,
Ну и молодец (на полном серьезе). Примерно так и оставить, мне только

aux_lo := aux_lo - aux_hi shl 32;

глаза режет. Т.к.:
1. Оно вообще не нужно. Приведение типа к (DWORD) само младшую часть и выделит.
2. AFAIK Обычно такие вещи общепринято делать через "двоичное И", наверное в Delph это and:

lo := value and 0xFFFFFFFF;

ну или как-то так

Какая нафиг оптимизация, когда у тебя одна операция умножения? Что Вы там оптимизируете? Во многих случаях, компилятор значительно более эффективный код сделает, т.к. авторы компиляторов обычно лучше знают правила и рекомендации Intel по написанию кода. Случайно вставив ассемблерную инструкцию которая даст "пенальти" или "промах" можно резко затормозить процессор на десятки тактов. Т.ч. все "улучшения" окажутся просто вредны.

Кроме того, если ф-цию сделать inline (наверняка Delphi это умеет), то компилятор сможет и окружающий код в точке ее вызова оптимизировать.

Если так уж хочется на ассемблере (что глупо и дико), то должно выглядить как-то так:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function __Mul(a, b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD

// rcx = a
// rdx = b
// r8 = hiDword
mov rax, rcx
mul rdx                   // rax:rdx = a*b   Я надеюсь )))
mov rax, edx           // rax = loDword. В новых процах это zero latency инструкцию. 0 тактов.
shr rdx, 32              // rdx = hiDword
mov dword ptr [r8], edx    // Подозреваю тут мы можем словить пенальти. Нужно читать гайды


Как-то так. Понятное дело не проверял. Возможны ошибки. Скорее всего "dword ptr" вообще не нужен, т.к. размер задаст edx.
...
Рейтинг: 0 / 0
16.12.2015, 15:44
    #39129890
Barlone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Умножение в ASM для x64-сборки
Leonid Kudryavtsev
Если так уж хочется на ассемблере (что глупо и дико), то должно выглядить как-то так:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function __Mul(a, b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD

// rcx = a
// rdx = b
// r8 = hiDword
mov rax, rcx
mul rdx                   // rax:rdx = a*b   Я надеюсь )))
mov rax, edx           // rax = loDword. В новых процах это zero latency инструкцию. 0 тактов.
shr rdx, 32              // rdx = hiDword
mov dword ptr [r8], edx    // Подозреваю тут мы можем словить пенальти. Нужно читать гайды


Как-то так. Понятное дело не проверял. Возможны ошибки. Скорее всего "dword ptr" вообще не нужен, т.к. размер задаст edx.
Не правильно.Parameters less than 64 bits long are not zero extended; the high bits are not zeroed
ecx = a, edx = b, при этом старшие биты rcx,rdx не определены...
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Умножение в ASM для x64-сборки / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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