Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.12.2014, 09:57   #11
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

  1. Код:
    ; masm dos com #
    .model tiny
    .286
    .CODE
    org 100h
    start:  mov ah,3Ch
            mov cx,0; атрибуты файла
            mov dx,offset filename
            int 21h
            retn
    filename db 'myfile.txt',0
    end start
  2. Код:
    ; masm dos com #
    .286
    .model tiny
    .code
    org 100h
    start:  mov ah,5Bh
            mov cx,0; атрибуты файла
            mov dx,offset filename
            int 21h
            retn
    filename db 'myfile.txt',0
    end start
  3. Код:
    ; masm dos com #
    .286
    .model tiny
    .code
    org 100h
    start:  mov cx,0; атрибуты файла - обычный файл
            mov bx,2 ;режим доступа чтение-запись
            mov dx,10h 
            mov si,offset filename;указатель на имя файла 
            mov ah,6Ch
            int 21h ;создаем файл 
            retn
    filename db 'myfile.txt',0
    end start
  4. создаем файл с длинным именем (до 255 символов) и чувствительным к регистру
    Код:
    ; masm dos com #
    .286
    .model tiny
    .code
    org 100h
    start:  mov cx,0; атрибуты файла - обычный файл
            mov bx,2 ;режим доступа чтение-запись
            mov dx,10h 
            mov si,offset filename;указатель на имя файла 
            mov ax,716Ch
            int 21h 
            retn
    filename db 'myfile.txt',0
    end start
  5. через FCB
    Код:
    ; masm dos com #
    .286
    .model tiny
    .code
    org 100h
    FCB struct
            drive_num       db ?
            file_name       db 8 dup(20h)
            file_ext        db 3 dup(20h)
            block_num       dw ?
            record_size     dw ?
            file_size       dd ?
            file_data       dw ?
            rezerved        db 10 dup(?)
            current_rec     db ?
            random_rec      dd ?
    FCB ends
    start:  mov ah,16h
            mov dx,offset fcb
            int 21h
            ret
    fcb FCB <0,'myfile','txt'>
    ;0 - диск по умолчанию, далее 8-байтовое имя файла
    ;если меньше, то заполняется пробелами, далее 3-байтовое расширение
    end start
  6. создаем файл при помощи набора команд DOS
    Код:
    ; masm dos com #
    .286
    .model tiny
    .code
    org 100h
    start:  mov bx,100h     ;выделим блок памяти в 256 параграфов
            mov ah,4Ah               
            int 21h
            mov bx,offset parametrs ;указываем на блок параметров
            mov [bx+4],cs
            mov dx,offset filename
            mov ax,4B00h;загрузить и выполнить программу из командной строки
            int 21h
            retn        ;выход в DOS
    command_line db N,'/c copy nul myfile.txt',0Dh
    N = $-command_line-1;длина командной строки
    ;командная строка типа pascal, начинается с байта длины строки, заканчивается
    ;ASCII-кодом клавиши Enter (0Dh). При передаче команды CMD.EXE нужно указать /С перед 
    ;строкой (требование вызова вторичного командного процессора). Программу cmd.exe
    ;из папки windows\system32\ проще разместить в том же каталоге, что и программа 
    filename db 'cmd.exe',0
    parametrs dw 0,command_line,5 dup(0);блок параметров
    end start
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:05   #12
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

7. Загрузить COMMAND.COM и настроить его по месту в памяти не используя функцию 4Bh прерывания 21h
Код:
; masm dos com #
.286
.model tiny
.code
org     100h
start:  mov ah,4Ah      ;модифицируем назначенную память
        mov bx,100h     ;новый размер блока в параграфах
        int 21h         
        or bx,-1        ;требуемое число параметров для выполнения
        mov ah,48h      ;выделить блок памяти
        int 21h         ;возвращает в bx размер наибольшего доступного блока 
;памяти в параграфах
        mov ah,48h      ;выделить блок памяти, в bx действительно доступная память
        int 21h         ;возвращает в ах сегментный адрес выделенного блока
        mov es,ax       ;es:=new PSP
        mov ss,ax       ;ss:=new PSP
        xchg dx,ax      ;dx:=new PSP
        mov ah,26h      ;создать новый префикс программного сегмента
        int 21h         
        mov dx,offset filename
        mov di,80h      ;указатель на командную строку
        mov cx,(N+1)/2  ;копируем по два байта за раз, N округлен в большую 
;сторону к числу кратному два, поэтому добавочный movsb не нужен
        mov si,offset command_line
        rep movsw       ;создаем командную строку для запуска command.com
        mov ax,3D00h    ;открыть command.com на чтение
        int 21h
        xchg bx,ax      ;дескриптор файла в bx
        xor cx,cx       ;cx=dx=0
        xor dx,dx
        mov ax,4202h    ;установить файловый указатель на конец файла
        int 21h
        push ax         ;сохраним в стеке длину файла command.com
        mov ax,4200h    ;установить файловый указатель на начало файла
        int 21h
        mov dx,es       ;пересчитываем чему должен быть равен dx из расчета,
        add dx,10h      ;что cs*10h+dx=es*10h+100h
        mov cx,cs
        sub dx,cx
        shl dx,4        ;в dx адрес буфера, куда будет скопирован command.com
        pop cx          ;в сх число байтов для чтения 
        mov ah,3Fh      ;читаем command.com в буфер
        int 21h
        mov ah,3Eh      ;закрыть файл command.com
        int 21h
        mov ax,es       ;ds:=new PSP
        mov ds,ax       ;при старте СОМ-файла cs=ds=es=ss=PSP ip=100h
        push es         ;новое значение cs:=new PSP
        push 100h       ;новое значение ip:=100h
        retf            ;запускаем command.com для создания файла myfile.txt
filename db 'c:\windows\system32\command.com',0;полный путь к command.com
command_line db N-1,'/c copy > myfile.txt',0Dh
N = $ - command_line
db 0; если N нечетное, то копируется и добавочный нулевой символ 
end     start
8. имитируем вызов int 21h
Код:
; masm dos com #
.286
.model tiny
.code
org 100h
start: mov cx,0        ;атрибуты файла (обычный файл)
;получаем дальний адрес (cs:ip) обработчика 
;прерывания 21h из таблицы векторов прерывания
        mov es,cx;сегментный адрес таблицы векторов прерывания в es                          
        les bx,es:[21h*4];сегмент и смещение обработчика прерывания 21h        
;параметры для функции 3Ch прерывания 21h        
        mov dx,offset filename;имя создаваемого файла
        mov ah,3Ch      ;номер функции
;три параметра в стек для возврата из прерывания
        pushf           
        push cs
        push offset @f  ;адрес возврата
;имитируем вызов int 21h
        push es         ;cs для int 21h
        push bx         ;ip для int 21h
        retf            ;подменяем cs и ip
@@:     ret      ;выход из программы
filename db 'myfile.txt',0
end start
9.
Код:
; masm dos com #
.286
.model tiny
.code
org 100h
FCB struct
    drive_num   db ?
    file_name   db 8 dup(20h)
    file_ext    db 3 dup(20h)
    block_num   dw ?
    record_size dw ?
    file_size   dd ?
    file_data   dw ?
    rezerved    db 10 dup(?)
    current_rec db ?
    random_rec  dd ?
FCB ends
start:  push offset @f    ; Занести в стек флаги, сегмент
    push cs           ;    и смещение адреса возврата
    pushf             ;    в обратном порядке.
    mov cl,16h
    mov dx,offset fcb
    jmp dword ptr ALT_DOS_PTR ; Выполнить функцию.
@@: mov ah,4Ch
    int 21h 
fcb FCB <0,'myfile','txt'>
;0 - диск по умолчанию, далее 8-байтовое имя файла
;если меньше, то заполняется пробелами, далее 3-байтовое расширение
ALT_DOS_PTR dw  0C0h,0;адрес для перехода в альтернативный обработчик
end start
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:10   #13
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

10. Перечитывая Зубкова наткнулся на еще один способ
Код:
; masm dos com #
.286
.model tiny
.code
org 100h
start:  mov si,offset string    
    mov cx,N
@@: push cx
    lodsb
    mov ah,5      ;номер функции
    mov cl,al;передача параметра через регистр CL, содержимое CH=0 
    int 16h
    pop cx
    loop @b
    retn
string db 'copy>myfile.tx',0Dh; не более 15 символов
N = $ - string
end start
Там в главе "Основы программирования для MS-DOS" 4.4.2 Ввод с клавиатуры. Средства BIOS. Пример, который имитирует набор на клавиатуре команды DIR, через 5 функцию 16h прерывания. Но стоит примечание
Цитата:
"Например, следующая программа при запуске из DOS вызывает команду DIR (но при запуске из некоторых оболочек, например FAR, этого не произойдет)."
У меня под FAR'ом программа работала, но попытка создать файл через "COPY > myfile.txt" не работала, пока опытным путем я не установил, что длина всей строки не должна быть больше 15 символов, обязательно заканчиваться на 0Dh (ASCII-код Enter)
11. через int 2Eh
Код:
; masm dos com #
.286
.model tiny
.code
org 100h
start:  mov ah,4Ah  ;allow mem alloc.
    mov bx,10h  ;новый размер блока в параграфах
    int 21h     
    mov si,offset command_line
    int 2Eh ; execute a command using BASE LEVEL
    mov ah,4Ch  ;выходим из программы
    int 21h
command_line db N,'copy > myfile.txt',0Dh
N = $ - command_line - 1
end  start
MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА
Цитата:
Прерывание 2Eh. "backdoor" для командного процессора
Обычно для обработки команды с помощью командного процессора COMMAND.COM используется функция EXEC (функция 4Вh прерывания "int 21h"). Однако, альтернативный, быстрый и "грубый" метод выполнения той же функции обеспечивает прерывание "int 2Eh". Чтобы выполнить какую-либо команду операционной системы MS-DOS, вначале уплотняется память с целью выделения места для новой программы (как и в случае функции 4Вh прерывания "int 21h" ), затем заносят в регистр DS: SI указатель на строку параметров данной команды и в конце обрабатывается прерывание "int 2Eh". Первый байт в строке параметров данной команды - это длина строки, за ней следует сама строка (например, "FORMAT C:"), которая заканчивается символом "возврат каретки" (0Dh). Этот завершающий символ считается частью длины строки. После того как прерывание "int 2Eh" обработано, важным моментом является обнуление стека, поскольку в результате прерывания "int 2Eh" содержимое регистров SS и SP может не сохраниться.
На самом деле символ 0Dh можно как включать в длину строки, так и не включать в неё — и в том и в другом случае программа работает. По всей видимости int 2Eh используется в Волков Коммандере (VC.COM), по крайней мере, у Всеволода В. Волкова в book.lib.rus.ec/books/VCINFO.TXT я нашел такую фразу
Цитата:
9. Предусмотрено два способа запуска команд из VC. Первый из них стандартный, запускает COMMAND.COM /C <команда>. При этом лишь требуется, чтобы переменная COMSPEC в окружении DOS была корректно установлена и наличие командного процессора по указанному пути. Это для тех, кто не любит рисковать (по-умолчанию). Второй способ, с использованием прерывания int 2Eh, работает не всегда (NDOS его просто не поддерживает). Этот способ предоставляет некоторые преимущества по сравнению с первым: позволяет изменять первичное окружения DOS командами SET, PATH, PROMPT и др., не загружается вторичная копия COMMAND.COM, поэтому команды выполняются быстрее и при загрузке резидентных программ в памяти не остается дырка от COMMAND.COM. Есть и несколько недостатков, заложенных в DOS: прерывание BATCH-файла с помощью Ctrl-Break останавливает выполнение, но при попытке выполнить следующую команду, сначала продолжается выполнение прерванного BATCH-файла, а лишь потом выполняется требуемая команда; DOS не предусматривает вложенное выполнение через int 2Eh, и поэтому, если одна программа запущена через int 2Eh запустила другую программу тоже через int 2Eh, то после завершения последней, управление передается процессу, запустившему первую программу, а первая программа остается в памяти, хотя доступа к ней нет. В итоге выбор остается за Вами. Второй способ запуска команд выбирается включением опции Quick execute commands в конфигурации.
12.
Код:
; masm dos com #
.286
.model tiny
.code
org 100h
start:  xor cx,cx; атрибуты файла
    mov es,cx
    les bx,es:[4*21h];читаем адрес текущего обработчика int 21h
    mov ofs21,bx
    mov seg21,es
    mov ah,3Ch
    mov dx,offset filename
    pushf; вызываем прерывание 21h
    db 9Ah;дальний вызов процедуры с указанием непосредственного адреса
    ofs21 dw ?
    seg21 dw ?
    retn
filename db 'myfile.txt',0
end start
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:16   #14
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

13.
Код:
; masm dos com #
.286
.model tiny
.code
org 100h
start:  xor cx,cx; атрибуты файла
    push ds
    mov ds,cx
    mov si,4*21h;читаем адрес текущего обработчика int 21h
    mov di,offset ofs21
    movsw
    movsw
    pop ds
    mov ah,3Ch
    mov dx,offset filename
    pushf
    call dword ptr ofs21; вызываем прерывание 21h
    retn
filename db 'myfile.txt',0
ofs21 dd ?
end start
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:21   #15
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

ОСНОВНЫЕ ПРАВИЛА НАПИСАНИЯ ПРОГРАММ НА ЯЗЫКЕ АССЕМБЛЕРА
Данные правила относятся не только к программированию на языке ассемблера, но и к программированию на других языках. Может быть, их трудно понять, не имея навыка в программировании, но «незнание основ не освобождает от ответственности».
Начинайте с комментариев
Начните с написания инструкции для пользователя — для чего создается и каковы возможности вашей программы. А теперь немного усложните вашу инструкцию по применению вашей программы, подразумевая под «пользователем» программиста, использующего написанный вами код — зачастую этим программистом-исследователем будете вы сами.
Акт записи на обычном языке описания того, что делает программа и что делает каждая функция в программе, является критическим шагом в мыслительном процессе. Хорошо построенное, грамматически правильное предложение — признак ясного мышления. Если вы не можете это записать, то велика вероятность того, что вы не полностью продумали задачу или метод ее решения. Плохая грамматика и построение предложения являются также показателем поверхностного мышления. Поэтому первый шаг в написании любой программы — записать, что именно и как делает программа.
Итак, комментарии для вашей программы уже готовы. Теперь возьмите ваше описание по использованию и добавьте вслед за каждым абзацем блоки кода, реализующие функции, описанные в этом абзаце. Оправдание: «У меня не было времени, чтобы добавить комментарии» на самом деле означает — «Я писал этот код без проекта системы и у меня нет времени воспроизвести его». Если создатель программы не может воспроизвести идеи, воплощенные в программный проект, то кто же тогда сможет?
Работа программиста состоит из двух частей: разработать приложение для пользователя и сделать возможным дальнейшее сопровождение программы. Единственный способ решить вторую часть задачи — комментировать код. Причем комментарии должны описывать не только, что делает код, но и предположения, принятый подход и причины, по которым вы выбрали именно его. Кроме того, необходимо, чтобы комментарии также соответствовали коду. Пишите код так, словно тот, кто будет заниматься его поддержкой, — опасный психопат, знающий где вы живете. Хотя вы можете считать, что ваш код полностью очевиден и может служить примером ясности, без правильных комментариев понять его постороннему достаточно трудно. Парадокс заключается в том, что спустя неделю вы сами можете оказаться в роли этого постороннего.
Старайтесь использовать следующий подход при написании комментариев:
  • перед каждой функцией или методом размещается одно или два предложения со следующей информацией:
    • что делает программа;
    • возникающие при этом предположения о программе;
    • что должно содержаться во входных параметрах;
    • что должно содержаться во выходном параметре в случае успешного или неудачного завершения;
    • все возможные выходные значения;
  • перед каждой не совсем очевидной частью функции следует поместить одно или два предложения, объясняющие выполняемые действия;
  • любой интересный алгоритм заслуживает подробного описания;
  • любая нетривиальная ошибка, устраненная в коде, должна комментироваться, при этом нужно привести номер ошибки и описать сделанное исправление;
  • правильно размещенные операторы диагностики, проверки условий, а также соглашения об именах переменных могут также служить хорошими комментариями и передавать содержание кода;
  • писать комментарии так, будто сами собираетесь заниматься его поддержкой через пять лет;
  • если возникла мысль «это хитро сделано» или «это ловкий трюк» — лучше переписать данную функцию, а не комментировать ее.
Если вы будете правильно писать комментарии – вы в безопасности, даже если программист из службы поддержки окажется психопатом.
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:21   #16
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

Читайте код
Все писатели — это читатели. Вы учитесь, когда смотрите, что делают другие писатели. Я настоятельно рекомендую, чтобы, как минимум, члены группы программирования читали код друг у друга. Читатель может найти ошибки, которые вы не увидели, и подать мысль, как улучшить код. Для вас лучше присесть с коллегой и просто разобрать код строка за строкой, объясняя, что и как делается, получить какую-то обратную связь и совет. Для того чтобы подобное упражнение принесло пользу, автор кода не должен делать никаких предварительных пояснений. Читатель должен быть способен понимать код в процессе чтения. Если вам пришлось объяснять что-то вашему читателю, то это значит, что ваше объяснение должно быть в коде в качестве комментария. Добавьте этот комментарий, как только Вы его произнесли; не откладывайте этого до окончания просмотра.
Разлагайте сложные проблемы на задачи меньшего размера
На самом деле это также и правило литературного стиля. Если очень трудно объяснить точку зрения за один раз, то разбейте изложение на меньшие части и по очереди объясняйте каждую. То же самое назначение у глав в книге и параграфов в главе.
Используйте язык полностью
Некоторые программисты считают одним из недостатков языка ассемблера большее, по сравнению с языками высокого уровня, количество команд, но, по-моему, это одно из достоинств языка ассемблера.
Проблема должна быть хорошо продумана перед тем, как она сможет быть решена
Это относится не только к программированию на языке ассемблера.
Отредактируйте свой код.
Программа должна писаться не менее двух раз

Раньше, когда вы изучали в школе литературу, вам никогда не приходило в голову сдавать черновик письменного задания, если Вы, конечно, рассчитывали на оценку выше тройки. Тем не менее, многие компьютерные программы являются просто черновиками и содержат столько же ошибок, сколько и черновики ваших сочинений. Хороший код программы должен быть сначала написан, а затем отредактирован в целях улучшения (под «редактированием» имеется в виду «исправление»). Редактирование, как правило, приводит к сокращению кода, а небольшие программы выполняются быстрее.
Оптимизация программ на языке ассемблера
Итак ваша программа заработала, а теперь постарайтесь переделать ее так, чтобы она стала максимально компактной и в тоже время максимально быстродействующей.
Такая оптимизация достигается в три этапа:
  • Алгоритмическая оптимизация то есть подбор алгоритма, который выполняет вашу задачу более быстрым способом и позволит сократить не пять, а пятьдесят операторов;
  • Подстройка программы под конкретное оборудование;
  • Замена некоторых ассемблерных команд на машинный код. Тщательный анализ машинного кода, вырабатываемого транслятором, позволяют прийти к выводу, что некоторые коды человек может выработать более оптимально, чем программа.
Для написания этого топика были использованы статьи из следующих книг
  1. Ален И. Голуб «Правила программирования С & С++» — М. : БИНОМ, 1996. — 272 с.
  2. Джон Роббинс «Отладка Windows-приложений» — М.: ДМК Пресс, 2001. — 448 с., ил.
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:29   #17
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

Флёнов Михаил Евгеньевич — российский программист, работал в журнале "Хакер" (рубрики "Hack-FAQ" и "Кодинг для программистов"), печатался в журналах "Игромания" и "Chip-Россия", автор книг по программированию и работе на компьютере:
  • Библия C#
  • Web-сервер глазами хакера. Безопасность в интернете
  • Искусство программирования игр на С++
  • DirectX и Delphi. Искусство программирования. Программирование графики
  • DirectX и C++. Искусство программирования. Программирование графики
  • Transact-SQL
  • PHP глазами хакера
  • Linux глазами хакера
  • Компьютер глазами хакера. Безопасность
  • Программирование на C++ глазами хакера
  • Программирование в Delphi глазами хакера
  • Библия Delphi

Советы по оптимизации от Михаила Фленова

ЗАКОН # 1


Оптимизировать можно все. Даже там, где вам кажется, что все и так работает быстро, можно сделать еще быстрее.

Идеального кода не существует. Чтобы достичь максимального результата, нужно действовать последовательно и желательно в том порядке, который описан ниже.
Помните, что любую задачу можно решить минимум двумя способами, ваша цель — выбрать наилучший метод, который обеспечит желаемую производительность и универсальность.

ЗАКОН # 2

Первое, с чего нужно начинать, — поиск самых слабых и медленных мест. Зачем начинать оптимизацию с того, что и так работает достаточно быстро? Если вы будете оптимизировать сильные места, то можете нарваться на неожиданные конфликты. Да и эффект будет минимален.
Когда-то меня посетила одна невероятная идея — написать собственную игру в стиле Doom. Четыре месяца невероятного труда, и нечто похожее на движок уже было готово. Был создан один голый уровень, по которому можно было перемещаться, и я с чувством гордости побежал по коридорам. Предстояло добавить монстров и атрибуты, да еще и наделить все это искусственным интеллектом. Но кому нужен движок, который в "голом виде" тормозит со страшной силой?
Понятно что виртуальный мир нужно было оптимизировать. Целый месяц борьбы с кодом и вылизывания каждого оператора движка. Результат — всё стало прорисовываться на 10% быстрей, но "тормоза" не исчезли. Неожиданно выяснилось, что самое слабое место — вывод на экран. Движок просчитывал сцены достаточно быстро, а "пробоиной" был именно вывод изображения. Пара часов колдовства, и я выжал из видеокарты все возможное. Откомпилировав движок, я снова погрузился в виртуальный мир. Одно нажатие клавиши "вперед", и я очутился у противоположной стены. Никаких тормозов, сумасшедшая скорость просчета и моментальный вывод на экран.
Как видите, ошибка была в неправильном определении слабого места движка. Потрачен месяц на оптимизацию математики, а в результате мизерные 10% прироста в производительности. Но когда было найдено реально слабое звено, то производительность была повышена в несколько раз.
Начинайте оптимизацию со слабых мест. При ускорении работы самого слабого звена вашей программы, возможно, и не понадобится ускорять другие места. Вы можете потратить дни на оптимизацию сильных сторон и увеличить производительность только на 10% (что может оказаться недостаточным), или несколько часов на улучшение слабой части, и получить улучшение в 10 раз!
Слабые места компьютера

Некоторые программисты гонятся за мегагерцами процессора, но сидят на доисторической видеокарте от S3, жестком диске на 5400 оборотов и с 32 Мбайтами памяти. Посмотрите "потроха" своего компьютера и оцените его содержимое. Если вы увидели, что памяти у вас не более 64 Мбайт, то это — самое слабое звено, купите себе 128, а лучше 256, а еще лучше 512 Мбайт памяти и наслаждаетесь ускорением работы Delphi, Photoshop и других "тяжелых" программ.
Наращивание сотни мегагерц у процессора даст более маленький прирост в скорости. Если вы используете тяжелые приложения при нехватке памяти, то процессор начинает тратить слишком много времени на загрузку и выгрузку данных. Если в вашем компьютере достаточно оперативной памяти, то процессор уже занимается только расчетами и не расходуется по лишним загрузкам-выгрузкам.
То же самое с видеоадаптером. Если видеокарта "слабенькая", то процессор будет просчитывать сцены быстрей, чем они будут выводиться на экран. А это грозит простоями и минимальным приростом производительности.
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:33   #18
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

ЗАКОН # 3
Следующим шагом вы должны разобрать все операции по косточкам и выяснить, где происходят регулярно повторяющиеся операции. Начинать оптимизацию нужно именно с них.
Допустим, у вас есть следующая программа:
Код:
А:=А*2;
B:=1;
Х:=Х+М[B];
B:=B+1;
Если B<100 то перейти на шаг 3.
Слабым местом является первая строка, потому что там используется умножение. Это действительно так. Умножение всегда выполняется дольше, и если заменить его на сложение (А:=А+А) или еще лучше на сдвиг, тогда выиграем пару тактов процессорного времени. Но только пару тактов, и для процессора это будет незаметно.
Теперь посмотрите еще раз на наш код. Больше ничего не видно? Программа использует цикл: "Пока B<100, будет выполняться операция Х:=Х+М[B]". Это значит, что процессору придется выполнить 100 переходов с шага 5 на шаг 3. А это немало. Можно ли что-нибудь оптимизировать? Внутри цикла выполняется две строки: 3 и 4. А что, если мы внутри цикла размножим их 2 раза:
Код:
B:=1;
Х:=Х+М[B]+М[B+1];
B:=B+2;
Если B<100 то перейти на шаг 2;
Сэкономлено 50 операций переходов. Неплохо? А это уже несколько сотен тактов процессорного времени.
А что, если совсем отказаться от операций перехода?
Код:
Х:=Х+М[1]+М[2]+М[3]+М[4]+М[5]+М[6]+М[7]+М[8]+М[9]+М[10];
Х:=Х+М[11]+М[12]+М[13]+М[14]+М[15]+М[16]+М[17]+М[18]+М[19]+М[20];
...
Х:=Х+М[91]+М[92]+М[93]+М[94]+М[95]+М[96]+М[97]+М[98]+М[99];
Недостаток этого подхода — увеличился объем программы, зато повысилась скорость, и очень значительно. Этот подход очень хорош, но им не стоит злоупотреблять. В любом деле главное — разумная достаточность. Чем больше вы увеличиваете код ради оптимизации скорости, тем меньше результирующий эффект от оптимизации.
Любую циклическую операцию можно оптимизировать. Допустим, у провайдера есть несколько телефонов доступа. Вы каждый день перезваниваете на каждый из них в надежде найти свободный. Хотя провайдер обязан оптимизировать свои пулы модемов в один, чтобы не надо было трезвонить по всем номерам сразу. Но не у каждого пользователя хорошая связь с любой телефонной станцией города. Поэтому провайдеры держат пулы на разных станциях, чтобы вы могли выбрать тот, с которым связь лучше. Поставьте программу-дозвонщик, которая сама будет перебирать номера телефонов.
Другой пример — вам на 1 час досталась карточка нового провайдера. Заносить ее в программу дозвона не имеет смысла, потому что вы можете больше никогда не позвонить ему. Из-за этой одноразовой операции вам придется перенастраивать свой дозвонщик на нового провайдера и потом обратно, а выигрыш практически нулевой, потому что пока вы меняете настройки, уже можно было дозвониться стандартными средствами Windows.
Вывод — правильно выбирайте средства для выполнения необходимых задач.

ЗАКОН # 4
(Этот закон — расширение предыдущего.)

Оптимизировать одноразовые операции — это только потеря времени. Сто раз подумай, прежде чем начать мучиться с редкими операциями.
Программисту нужно разослать приглашения на свадьбу. Вместо того чтобы набрать их на печатной машинке, программист пишет специальную программу. Написание заняло один день, столько же — отладка программы.
Главная ошибка — неправильная оптимизация своего труда. Легче набрать шаблон в любом текстовом редакторе и потом только менять фамилии приглашенных. Но даже если нет текстового редактора, писать программу действительно нет смысла. Затраты большие, а пользоваться — только один раз.
Получается, что одноразовые операции оптимизировать просто бессмысленно. Затраты в этом случае себя не окупают, поэтому не стоит тратить свои нервы на этот бессмысленный труд.
В данном случае крутым считается не тот, кто целый день промучился и ничего не добился, а тот, кто выполнил свою работу наиболее быстро и эффективно.
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:35   #19
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

ЗАКОН # 5


Нужно знать внутренности компьютера и принципы его работы. Чем лучше вы знаете, каким образом компьютер будет выполнять ваш код, тем лучше вы сможете его оптимизировать.
Тут трудно привести полный набор готовых решений, но некоторые приемы я постараюсь описать.
Старайтесь поменьше использовать вычисления с плавающей запятой. Любые операции с целыми числами выполняются в несколько раз быстрее.
Операции умножения и тем более деления также выполняются достаточно долго. Если вам нужно умножить како-то число на 3, то для процессора будет легче три раза сложить одно и то же число, чем выполнить умножение.
А как же тогда экономить на делении? Вот тут нужно знать математику. У процессора есть такая операция, как сдвиг. Вы должны знать, что процессор думает в двоичной системе, и числа в компьютере хранятся именно в ней. Например, число 198 для процессора будет выглядеть как 11000110. Теперь посмотрим, как работают операции сдвига.
Сдвиг вправо — если сдвинуть число 11000110 вправо на одну позицию, то последняя цифра исчезнет, и останется только 1100011. Теперь введите это число в калькулятор и переведите его в десятичную систему. Ваш результат должен быть 99. Как видите — это ровно половина числа 198.
Вывод: когда вы сдвигаете число вправо на одну позицию, то вы делите его на 2.
Сдвиг влево — возьмем то же самое число 11000110. Если сдвинуть его влево на одну позицию, то с правой стороны освободится место, которое заполняется нулем — 110001100. Теперь переведите это число в десятичную систему. Должно получится 396. Что оно вам напоминает? Это 198, умноженное на 2.
Вывод: когда вы сдвигаете число вправо, то вы делите его на 2; когда сдвигаете влево, то умножаете его на 2. Так что используйте эти сдвиги везде, где возможно, потому что сдвиги работают в десятки раз быстрее умножения и деления.
При создании процедур не обременяйте их большим количеством входных параметров. Перед каждым вызовом процедуры ее параметры поднимаются в специальную область памяти (стек), а после входа изымаются оттуда. Чем больше параметров, тем больше расходы на общение со стеком.
Тут же нужно сказать, что вы должны действовать аккуратно и с самими параметрами. Не вздумайте пересылать процедурам переменные, которые могут содержать данные большого объема в чистом виде. Лучше передать адрес ячейки памяти, где хранятся данные, а внутри процедуры работать с этим адресом. Вот представьте себе ситуацию, когда вам нужно передать текст размером в один том "Войны и мира".... Перед входом в процедуру программа попытается вогнать все это в стек. Если вы не увидите его переполнения, то задержка точно будет значительная.
В самых критичных моментах (как, например, вывод на экран) можно воспользоваться языком Assembler. Даже встроенный в Delphi или C++ ассемблер намного быстрее штатных функций языка. Ну а если скорость в каком-то месте уж слишком критична, то код ассемблера можно вынести в отдельный модуль. Там его нужно откомпилировать с помощью компиляторов TASM или MASM и подключить к своей программе. Ассемблер достаточно быстрая и компактная вещь, но писать достаточно большой проект только на нем — это очень сложно. Поэтому я советую им не увлекаться и использовать его только в самых критичных для скорости местах.
ЗАКОН # 6

Для сложных расчетов можно заготовить таблицы с заранее рассчитанными результатами и потом использовать эти таблицы в реальном режиме времени.
Когда появился первый Doom, игровой мир поразился качеству графики и скорости работы. Это действительно был шедевр программистской мысли, потому что компьютеры того времени не могли рассчитывать трехмерную графику в реальном времени. В те годы еще даже и не думали о ЗD-ускорителях, и видеокарты занимались только отображением информации и не выполняли никаких дополнительных расчетов.
Как же тогда программистам игры Doom удалось создать трехмерный мир? Секрет прост — во время игры микропроцессор не просчитывает сцены, все сложные математические расчеты были сделаны заранее и занесены в базу данных, которая запускается при старте программы. Конечно же занести все возможные результаты невозможно, поэтому база хранила основные результаты. Когда нужно было получить расчет значения, которого не было в заранее рассчитанной таблице, то бралось наиболее приближенное число. Таким образом, Doom получил отличную производительность и достаточное качество ЗD-картинки.
Оцените качество освещения и теней в сценах виртуального мира игры Quake. Совмещение высокого графического качества сцен и в то же время высокой скорости работы игры сделано за счет таблиц с заранее рассчитанными значениями.
Mikl___ вне форума Ответить с цитированием
Старый 03.12.2014, 10:36   #20
Mikl___
Участник клуба
 
Регистрация: 11.01.2010
Сообщений: 1,162
По умолчанию

ЗАКОН # 7
Лишних проверок не бывает.
Чаще всего оптимизация может привести к нестабильности исполняемого кода, потому что для увеличения производительности некоторые убирают ненужные на первый взгляд проверки. Запомните, что ненужных проверок не бывает! Если вы думаете, что какая-то нестандартная ситуация может и не возникнуть, то она не возникнет только у вас. У пользователя, который будет использовать вашу программу, может возникнуть все, что угодно. Он обязательно нажмет на то, на что не нужно, или введет неправильные данные. Обязательно делайте проверки всего того, что вводит пользователь. Делайте это сразу же и не ждите, когда введенные данные понадобятся.
Не делайте проверки в цикле, а выносите за его пределы. Любые лишние операторы if внутри цикла очень сильно влияют на производительность, поэтому по возможности проверки нужно делать до или после цикла. Циклы — это слабое место любой программы, поэтому оптимизацию надо начинать именно с них и стараться не вставлять в них лишние проверки. Внутри циклических операций не должно выполняться ничего лишнего — ведь это будет повторено много раз!..

Итог

Здесь были изложены только основы оптимизации. Оптимизация — это процесс творческий, и в каждой отдельной ситуации к нему можно подойти с разных сторон.
Для более глубокого познания оптимизации вам нужно изучать принципы работы процессора и операционных систем.
Mikl___ вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Программа для шифрования раздела с виндой Жека90 Софт 1 12.06.2012 18:17
макрос для решения квадратных уравнений (перемещено из раздела Excel) sashkkk Помощь студентам 3 22.09.2010 23:06
Собираем команду для FAQ Aexx Свободное общение 112 14.10.2009 09:20
Формат по образцу для раздела... Busine2009 Microsoft Office Word 0 28.07.2009 08:05
Программа для копирования заданного раздела. С++ x007 Общие вопросы C/C++ 5 23.04.2009 23:52