Главное меню
Мы солидарны с Украиной. Узнайте здесь, как можно поддержать Украину.

Ассемблер vs. оптимизирующие компиляторы

Автор mnashe, октября 14, 2011, 14:06

0 Пользователи и 1 гость просматривают эту тему.

mnashe

Цитата: jvarg от октября 14, 2011, 11:47
Для тогдашних маленьких машин были и компиляторы высокоуровневых языков, однако именно потому для создания практических программ и использовался, в основном, ассемблер, что он позволял сократить объем программы даже на таких мелочах, как передача параметров через стек.
И не только объём программы, но и быстродействие.
Адепт единственного числа и безродового склонения
שָׁלוֹם עֲלֵיכֶם!

Drundia

Цитата: jvarg от октября 14, 2011, 11:47
Угу, только это лишние байты, что при тогдашних объемах памяти и быстродействии имело огромное значение.
Тогда лучше было не функции использовать, а goto.

Цитата: jvarg от октября 14, 2011, 11:47
Для тогдашних маленьких машин были и компиляторы высокоуровневых языков, однако именно потому для создания практических программ и использовался, в основном, ассемблер, что он позволял сократить объем программы даже на таких мелочах, как передача параметров через стек.
Ну да, передавайте через регистры... Только кто полезные значения из регистров и где сохранять будет? Правильно, в стэке.

Цитата: mnashe от октября 14, 2011, 14:06
И не только объём программы, но и быстродействие.
А нынче компиляторы умные пошли. Оптимизируют.

Python

ЦитироватьА нынче компиляторы умные пошли. Оптимизируют.
Не факт.
Пролетареві ніколи вчити європейських мов, бодай би свою знати добре і на ній принести до своєї хати світло знання (Гнат Хоткевич)
ÆC CASALI NAXI PRASQURI: AHOV CÆRU, MERTVÆRI TÆ SLAVUTÆT!
Вони просили його: «Скажи: кетум», а він говорив: «сатем», і не міг вимовити правильно.
Хотелось бы также отметить, что "Питон" - это "мышиный язык" : "пи+тон". © АБР-2

Drundia

Ну то что для базовых типов (a=a+b) === (a+=b) — знают.

Drundia

Цитата: Python от октября 14, 2011, 15:22
Не факт.
Ой-ой-ой, таки не факт, обнаружил жуткую ересь!

c = a/b; d = a%b;
даёт
mov     eax, DWORD PTR [esp+20]
mov     edx, DWORD PTR [esp+16]
mov     ecx, edx
cdq
idiv    ecx
mov     DWORD PTR [esp+24], eax
mov     eax, DWORD PTR [esp+20]
mov     edx, DWORD PTR [esp+16]
mov     ecx, edx
cdq
idiv    ecx
mov     DWORD PTR [esp+28], edx

mnashe

Цитата: Drundia от октября 14, 2011, 21:32
Цитата: Python от октября 14, 2011, 15:22
Не факт.
Ой-ой-ой, таки не факт, обнаружил жуткую ересь!

c = a/b; d = a%b;
даёт
mov     eax, DWORD PTR [esp+20]
mov     edx, DWORD PTR [esp+16]
mov     ecx, edx
cdq
idiv    ecx
mov     DWORD PTR [esp+24], eax
mov     eax, DWORD PTR [esp+20]
mov     edx, DWORD PTR [esp+16]
mov     ecx, edx
cdq
idiv    ecx
mov     DWORD PTR [esp+28], edx

Вот-вот.
Задача, кстати, весьма практическая: например, при переводе числа в строку.
И это не единственный случай. Если такое делается в многократно повторяющемся цикле, разница будет ощутимой.
Хотя, конечно, на шкале между древними компиляторами высоких языков и ассемблером современные компиляторы ближе к ассемблеру.
Адепт единственного числа и безродового склонения
שָׁלוֹם עֲלֵיכֶם!

Drundia

Вот-вот, и никакие оптимизации не спасают.

Ещё есть забавная задача с арифметикой по модулю. Без ассемблера никуда.

    if ((x+=rhs.x) < rhs.x) x-=n;
даёт
        mov     eax, DWORD PTR [edx+4]
        add     eax, DWORD PTR [ecx+4]
        mov     DWORD PTR [ecx+4], eax
        cmp     eax, DWORD PTR [edx+4]  ;ересь
        jae     L2
LVL1:
        sub     eax, DWORD PTR [ecx]
        mov     DWORD PTR [ecx+4], eax
L2:

Учитывая беззнаковость операндов, условие в if'е — это просто установка CF при сложении. Стало быть ересь не нужна. К счастью, jnc===jae. Впрочем, ассемблером можно и красивее, учитывая что нам потом нужен остаток от деления.

С умножением ещё веселее. Надо получить int64 из int32*int32, а потом найти остаток от деления этого int64 на int32. Нормальный код получить не выходит, а вот добрый дядя Интел всё необходимое предусмотрел.

Впрочем, GCC всё же неплохо умеет интегрировать сишный и ассемблийный код, что избавляет от ненужной мороки.
    asm (
        "mul %[b0]\n\t"
        "div %[d0]\n\t"
        :[a] "=d" (x)        // лучше "=&d"?
        :[a0] "a" (x), [b0] "g" (rhs.x), [d0] "g" (n)
    );



Вывод: языки высокого уровня для низкоуровневых задач не годятся.

mnashe

Цитата: Drundia от октября 16, 2011, 17:36С умножением ещё веселее. Надо получить int64 из int32*int32, а потом найти остаток от деления этого int64 на int32. Нормальный код получить не выходит, а вот добрый дядя Интел всё необходимое предусмотрел.
В моей программе есть специальная функция от трёх параметров — muldiv. Она такую цепочку как раз и задействует.
Остаток от деления, правда, отбрасывается, но пока в такой цепочке он мне не был нужен.
Посчитал, сколько раз эта функция используется у меня в макрях: 46.
Адепт единственного числа и безродового склонения
שָׁלוֹם עֲלֵיכֶם!

Drundia

Цитата: mnashe от октября 16, 2011, 18:02
В моей программе есть специальная функция от трёх параметров — muldiv. Она такую цепочку как раз и задействует.
Со всеми оптимизациями код
x = ((unsigned long long)x*rhs.x) % n;
даёт вполне пригодное умножение, но для остатка всё равно использует встроенную функцию для деления слишком длинных целых ___umoddi3 :( Надо будет посмотреть когда-нибудь, как она устроена.

В сложении явно использует при подобном коде больше регистров, чем надо.

Если преобразовывать уже результат умножения, то код для определения остатка вполне пригодный; но старшее слово теряется, что соответствует стандарту. Нехорошо.

Drundia

Продолжаю баловаться. Похоже что     if ((x+rhs.x) < rhs.x) x=x-n+rhs.x;
    else x+=rhs.x;
компилируется лучше (догадался, что (a+b)<a для беззнаковых — это тест кэрри-флэга, и даже догадался, что последующие операции сложения используют уже посчитанное x+rhs.x), чем
  if ((x+=rhs.x) < rhs.x) x-=n; Забавно.

Для уважаемых модераторов: думаю, не помешало бы кусок темы, посвящённый компиляции сишного (сиплюсплюсного) кода в x86-ассембли вынести в отдельную тему.

 

Быстрый ответ

Обратите внимание: данное сообщение не будет отображаться, пока модератор не одобрит его.

Имя:
Имейл:
Проверка:
Оставьте это поле пустым:
Наберите символы, которые изображены на картинке
Прослушать / Запросить другое изображение

Наберите символы, которые изображены на картинке:

√36:
ALT+S — отправить
ALT+P — предварительный просмотр