Иллюстрированный самоучитель по задачам и примерам Assembler

Использование счетчика меток реального времени 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, производящая перевод значения из двоичной системы в десятичную.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.