allasm.ru

    Меню

 

   Как было объяснено в главе 7, размер кода кэша равен 8 или 16 килобайтам. Если у вас есть подозрение, что критические части кода не поместятся в кэш, тогда вы можете подумать о том, чтобы уменьшить их размер.

   32-х битный код обычно больше, чем 16 битный код, потому что адреса и константы занимают 4 байта в 32-х битном режиме, а 16-ти битном режиме только два. Тем не менее, 16-ти битный код другие потери, такие как префиксы и проблемы с соседнеми словами памяти (смотри главу 10.2). Некоторые другие методы для уменьшения размера кода обсуждаются ниже.

   Оба адреса перехода, адреса данных и константы занимают меньше места, если их значение находится между -128 до +127.

   Для адресов переходов это означает, что короткие переходы занимают два байта, в то время как переходы более чем 127 байт занимают 5 байтов, если переход безусловный и 6 байтов, если условный.

   Таким же образом адреса данных занимают меньше места, если они могут быть выраженны как указатель в интервале от -128 до +127

Пример:

MOV EBX,DS:[100000] / ADD EBX,DS:[100004] ; 12 байт

Уменьшаем размер:

MOV EAX,100000 / MOV EBX,[EAX] / ADD EBX,[EAX+4] ; 10 байт

   Преимущество использования указателя становится еще более очевидным, если вы используете его много раз. Хранение данных в стеке и использование EBP или ESP в качестве указателя сделает ваш код меньше, чем если бы вы использовали абсолютные адреса, если только, конечно, ваши данные в пределах +/-127 байтах указателя. Использование PUSH и POP для записи и чтения временных данных еще короче.

   Константы могут также занимать меньше места, если они между -128 и +127. Большинство инструкций с числовыми операндами имеют короткую форму, где операнд - это один байт со знаком.

Примеры:

    PUSH 200      ; 5 байт
    PUSH 100      ; 2 байт

    ADD EBX,128   ; 6 байт
    SUB EBX,-128  ; 3 байт

Самая важная инструкция с числовым операндом, у которой нет короткой формы, это MOV.

Примеры:

    MOV EAX, 0              ; 5 байт

Можно заменить на:

    XOR EAX,EAX             ; 2 байта

И

    MOV EAX, 1              ; 5 байтов

Можно заменить на:

    XOR EAX,EAX / INC EAX   ; 3 байта

или:

    PUSH 1 / POP EAX        ; 3 байта

И

    MOV EAX, -1             ; 5 байта

Можно заменить на:

    OR EAX, -1              ; 3 байта

   Если один и тот же адрес или константа используется несколько раз, вы можете загрузить ее в регистр. MOV с 4-х байтным числовым операндом иногда можно заменить на арфметическую инструкцию, если известно значение регистра до MOV.

Пример:

        MOV     [mem1],200             ; 10 байтов
        MOV     [mem2],200             ; 10 байтов
        MOV     [mem3],201             ; 10 байтов
        MOV     EAX,100                ;  5 байтов
        MOV     EBX,150                ;  5 байтов

Предполагая, что mem1 и mem3 находятся в пределах -128/127 байтов от em2, это можно изменить на:

        MOV     EBX, OFFSET mem2       ;  5 байтов
        MOV     EAX,200                ;  5 байтов

        MOV     [EBX+mem1-mem2],EAX    ;  3 байта
        MOV     [EBX],EAX              ;  2 байта
        INC     EAX                    ;  1 байт
        MOV     [EBX+mem3-mem2],EAX    ;  3 байта
        SUB     EAX,101                ;  3 байта
        LEA     EBX,[EAX+50]           ;  3 байта

Остерегайтесь задержек AGI в инструкции LEA (для PPlain и PMMX).

   Также стоит учитывать то, что разные инструкции имеют разную длину. Следующие инструкции занимают только один байт и поэтому очень привлекательны: PUSH reg, POP reg, INC reg32, DEC reg32. INC и DEC с 8-ми битовыми регистрами занимают 2 байта, поэтому 'INC EAX' короче, чем 'INC AL'.

'XCHG EAX,reg' также однобайтовая инструкция и поэтому занимает меньше места, чем 'MOV EAX,reg', но это медленнее.

   Некоторые инструкции занимают на один байт меньше, когда они используют аккумулятор, а не другой регистр.

Пример:

    MOV EAX,DS:[100000]  меньше, чем  MOV EBX,DS:[100000]
    ADD EAX,1000         меньше, чем  ADD EBX,1000

   Инструкции с указателями занимают на один байт меньше, чем когда они используют адресацию по базе (не ESP) со сдвигом, а не косвенную адресацию с масштабированием, или и то, и другое вместе, или ESP в качестве базы.

Примеры:

    MOV EAX,[array][EBX]  меньше, чем  MOV EAX,[array][EBX*4]
    MOV EAX,[EBP+12]      меньше, чем  MOV EAX,[ESP+12]

   Инструкции с EBP в качестве базы без смещения занимают на один байто больше, чем при использовании других регистров:

    MOV EAX,[EBX]    меньше чем  MOV EAX,[EBP], но
    MOV EAX,[EBX+4]  такого же размера, как и MOV EAX,[EBP+4]

Также адресация со сдвигом бывает выгоднее, чем адресация с масштабированием:

    LEA EAX,[EBX+EBX]  короче, чем  LEA EAX,[2*EBX]