1. Вы находитесь в архивной версии форума xaker.name. Здесь собраны темы с 2007 по 2012 год, большинство инструкций и мануалов уже неактуальны.
    Скрыть объявление

Ассемблер x86 против C часть2

Тема в разделе "Assembler", создана пользователем Robo, 6 дек 2007.

  1. Robo

    Robo ░░▒▓█▓▒░░ Модератор

    Регистрация:
    10 авг 2007
    Сообщения:
    301
    Симпатии:
    169
    Баллы:
    0
    А компиляторы Си (из соображений портабельности? :) указателей с селекторами не поддерживает

    в принципе. остается либо при каждом обращении по указателю суммировать его с базой блока

    (подобное возможно за счет одного из "дополнений" в MSVC - тага __based - пример:

    Код:
        void *vpBuffer;
        struct llist_t
        {
          void __based( vpBuffer ) *vpData;
          llist_t __based( vpBuffer ) *llNext;
        }; 
    
    ) либо перебазировать каждый раз все ссылающиеся на блок указатели, либо как-то эмулировать

    селекторную систему.

    Может я и напишу когда-нибудь замену malloc etc на системных вызовах и __based'ных

    указателях... только в сложных случаях это может оказаться менее эффективно, чем стандартный

    способ - регистры закончатся в два раза быстрее. А вот селекторный вариант определенно

    быстрее - я проверял.

    А уж как чудно malloc'омания отражается на функциональности программ... :). В частности,

    архиваторам нужна опция для указания размера словаря, в первую очередь, именно чтобы его не

    realloc'ить.

    Ассемблер vs C
    А вот алгоритмическая часть значительно важнее, потому как ошибки там обычно стоят

    порядки...

    Вот-вот. Как ты думаешь, навязывание мне авторами компилятора flat-модели может влиять на

    выбор алгоритмов? Или... вспоминается мне, например, прикол, когда я написал макрос для

    выравнивания функций по parity младшего байта адреса :).

    Код:
     
    
    			mov     bp,offset OpTable
    GetNextChar:            lodsb
                            mov     ah,0
                            shl     ax,1
                            add     bp,ax
                            mov     bp,[word ss:bp]
                            inc     bp
    			jp      ExecuteOperator
                            loop    GetNextChar
    			...
    ExecuteOperator:	jmp	bp
    
    Это я интерпретатор писал, еще в XT'шные времена :). Там было некоторое множество

    операторов, и для их разбора я изобразил trie в виде наборов табличек, индексируемых

    очередным символом и содержащих либо адрес очередной таблички, либо адрес

    функции-обработчика. Которые отличались, как видно, по parity младшего байта адреса минус

    один - это оказалось несколько быстрее всех прочих приходивших мне в голову решений :). Дык

    вот. Слабо заставить компилятор сей скомпилить функцию по адресу с такими ограничениями? :)

    Или более серьезный пример - понадобился мне как-то словарь в виде тернарного дерева. Так

    вот когда я сделал ветвление после сравнения символов не по больше/меньше, а по parity...

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

    Или битовые операции те же. Ты знаешь, что на x86 есть возможность работать с битовыми

    массивами длины до 2^31, причем в обе "стороны" от указанного адреса? Т.е. команды для этого

    есть. Типа

    Код:
    mov eax,-10000
    m0:
    btr [ArrayEnd],eax
    inc eax
    jnz m0
    
    (это к вопросу о соотношении строк в сишном/асмовском исходниках)


    1. Умножение

    Для процессора, реализация умножения с выдачей двойного слова на выходе является очень

    логичной. (Аналогично с делением). Т.е. если сделать не так, то умножение в длинной

    арифметике придется делать сдвигами - что совсем не рулез :). ЯВУ, который бы это понимал,

    мне пока не попадался :(. Поэтому большинство арифметических кодеров, использующих деление,

    дают на несколько сотых процента худшее сжатие. Полкилобайта на метр архива - считай мусор,

    который обязан своим существованием ограничениям языка :).

    Причина: компилятор Си поймет запись

    Код:
       low += cumFreq * (range/= totFreq);
    
    правильно, а вот

    Код:
       low += (cumFreq*range)/totFreq
    
     

Поделиться этой страницей