Использование счетчика меток реального времени TSC
Ids si.adr_string_pack add si.len_string_pack-2:на конец string_pack (18 упак. дес. цифр) les di.adr_string movcx.9;9 пар упакованных десятичных цифр xor ax,ax cycl: xor ax,ax std;string_pack обрабатываем с конца lodsb;в al очередные 2 упакованные десятичные цифры распаковываем – аИ=младшая, а1=старшая shi ax.4 rol al.4 or ах.ЗОЗОп:преобразуем в символьное представление xchg ah.al:ап-младшая .al-старшая eld:в string записываем с начала stosw loop cycl ;………выводим на консоль…………………………. ' mov bx.l стандартный дескриптор – экран mov cx.len_string Ids dx.adr_string – . формируем указатель на строку string mov ah.40h:номер функции DOS int 21h:выводим jc exit;переход в случае ошибки endm profileMn macro val_l:REQ ;val_l – ячейка памяти 64 бита (2x32) для сохранения момента :начала профилирования ("грязного") pushad сохранение всех регистров общего назначения в стеке db Ofh.31h;RDTSC mov val_l+4.edx mov va!_l.eax popad восстановление всех регистров общего назначения из стека endm profiler_out macro val_l:REQ .val_2:REQ :val_l – ячейка памяти 64 бита (2x32). в которой при входе в макрос сохранен :момент начала профилирования командой profilerjn. Далее в макросе эта ячейка :содержит результат профилирования – число тактов процессора :val_2 – ячейка памяти 64 бита (2x32) ; в которой сохраняется момент ("грязный") окончания профилирования pushad сохранение всех регистров общего назначения в стеке db 0fh,31h :RDTSC – окончание профилирования mov val_2+4.edx mov val_2,eax профилируем pushad и popad с учетом двух shrd pushad popad db 0fh.31h;RDTSC :теперь необходимо получить чистое время профилирования, для чего результат ;необходимо скорректировать (уменьшить) на количество тактов процессора, :потребное для выполнения пар команд PUSHAONPOPAD и M0V subeax, val_2 jnc $+4:учет заема из старшего разряда dec edx subedx .val_2+4;в edx:eax кол-ва тактов для выполнения 2-х команд ;PUSHAD\POPAD и 2-х SHRD mov eax,val_l sub val_2.eax mov eax.val_l+4 jnc $+7:учет заема из старшего разряда при выполнении предыдущего вычитания dec val_2+4 sub val_2+4,eax ;в val_2:val_2+4 – чистое количество тактов процессора для выполнения профилируемого участка popad восстановление всех регистров общего назначения из стека :выводим bin_dec_fpu val_2_q .string_pack, adr_string_pack, len_string_pack .adr_string .len_string endm.data val_2 label dword val_2_q dq 0 val_l label dword dq 0 :b string_pack исходное значение из val_2_q в упакованном десятичном формате string_pack dt О len_string_pack=$-string_pack adr_stringpack dd string_pack string db 18 dup (0) максимальный результат состоит из 18 десятичных цифр len_string=$-string adr_string dd string .code профилируем выполнение команд работы со стеком profiIer_i n val_l push eax pop eax profiler_out val_l .val_2 exit::выход из программы
Составьте тестовые примеры и "поиграйтесь" с данной программой. Обратите внимание, что при задании пустой последовательности команд между парой макросов profilerin и profiler_out все равно получается некоторая величина профилирования. Она постоянна, ее источник – сами команды RDTSC, которые требуют тактов процессора для своего исполнения. Эту величину можно скорректировать разными способами, но можно и не трогать, а учитывать при подведении окончательных результатов тестирования нужного вам фрагмента кода. На компьютере автора эта величина равна 52.
В этой программе для визуализации результатов профилирования разработана макрокоманда bin_dec_fpu, производящая перевод значения из двоичной системы в десятичную.