Как было объяснено в главе 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]
[C] Агнер Фог, пер. Aquila