1 ЛЕКЦИЯ 12 ИСПОЛЬЗОВАНИЕ СЧЕТЧИКА МЕТОК РЕАЛЬНОГО ВРЕМЕНИ Счетчик меток реального времени TSC (Time Stamp Counter) – 64 – разрядный регистр, содержимое которого инкрементируется с каждым тактом процессорного ядра. Каждый раз при аппаратном сбросе (сигналом RESET) отсчет в этом счетчике начинается с нуля. Разрядность регистра обеспечивает счет без переполнения в течение сотен лет. Счетчик продолжает счет как при исполнении инструкции HLT, так и при остановке процессора по сигналу STPCLK# (для энергосбережения). Чтение счетчика обеспечивает инструкция RDTSC, установкой бита CR4.TSD ее можно сделать привилегированной (доступной лишь при СPL = 0). Присутствие счетчика TSC определяется по инструкции CPUID (EAX = 1). Если в результате ее вызова бит 4 регистра EDX равен 1, то процессор поддерживает счетчик меток реального времени.
2 Команда RDTSC (Read from TSC) – чтение 64-разрядного счетчика меток реального времени, не имеет операндов. Машинный код этой команды – 0f31. Команда проверяет состояние второго бита регистра CR4.TSD (Time Stamp Disable – отключить счетчик меток реального времени): - если CR4.TSD = 0, то выполнение команды RDTSC разрешается на любом уровне привилегий; - если CR4.TSD = 1, то выполнение команды RDTSC разрешается только на нулевом уровне привилегий. Если после данной проверки выполнение команды разрешено на текущем уровне привилегий, то выполняется сохранение значения 64-битного счетчика TSR в паре 32-битных регистров EDX:EAX. Если выполнение команды запрещено, то работа команды заканчивается. Эту возможность современных процессоров можно использовать для количественной оценки разрабатываемого кода.
3 В качестве примера рассмотрим создание и использование макрокоманд, основанных на использовании команды RDTSC, предназначенных для определения продолжительности выполнения исследуемых участков кода. Такое действие называется профилированием. Вызов первой макрокоманды, под названием profiler_in, должен зафиксировать момент, относительно которого будет производиться отсчет тактов процессора, то есть производиться в начале профилируемого участка. Вызов второй макрокоманды profiler_out должен зафиксировать момент окончания работы на этом участке программы. Необходимо иметь в виду, что это «грязное» время работы программы, по которому можно производить только приблизительную оценку ее скорости работы. Для этого есть внутренняя и внешняя причины. Внутренняя причина заключается в том, что полученная величина включает время, затраченное на работу некоторых команд, составляющих тело самой макрокоманды. Этот недостаток исправить легко. Что касается внешних причин, то они объективны по отношению к программам пользователя и мешают получению истинного времени профилирования. В основе этих внешних причин лежит механизм вытесняющей многозадачности.
4 Исходные тексты макрокоманд profiler_inmacroval_1:REQ ; ;val_1 - ячейка памяти 64 бита (2ґ32) для сохранения момента начала профилирования ("грязного") ; pushad;сохранение всех регистров общего назначения в стеке db0fh,31h;RDTSC movval_1+4,edx movval_1,eax popad;восстановление всех регистров общего назначения из стека endm
5 profiler_outmacroval_1:REQ, val_2:REQ ; ;val_1 - ячейка памяти 64 бита (2х32), в которой при входе в ;макрос сохранен момент начала профилирования командой ;profiler_in. Далее в макросе эта ячейка содержит результат ;профилирования - число тактов процессора ;val_2 -ячейка памяти 64 бита (2х32), в которой сохраняется ;момент ("грязный") окончания профилирования ; pushad;сохранение всех регистров общего назначения в стеке db0fh,31h;RDTSC - окончание профилирования movval_2+4,edx movval_2,eax ;профилируем pushad и popad с учетом двух shrd pushad;2 popad;2 db0fh,31h;RDTSC
6 ; ;теперь необходимо получить чистое время профилирования, для чего ;результат необходимо скорректировать (уменьшить) на количество ;тактов процессора, потребное для выполнения пар команд ;pushad\popad и mov ; subeax, val_2 sbbedx, val_2+4; в edx:eax кол-ва тактов для выполнения 2-х команд pushad\popad и 2-х mov addval_1,eax adcval_1+4,edx moveax,val_1 movedx,val_1+4 subval_2,eax sbbval_2+4,edx
7 ;в val_2:val_2+4 - чистое количество тактов процессора для выполнения профилируемого участка popad;восстановление всех регистров общего назначения из стека endm Данные выше макрокоманды необходимо также дополнить макрокомандой вывода на консоль десятичного числа с результатом.