Курсовой проект - RDTSC
.doc
З
3
На языке ассемблера разработать программу определения внутренней тактовой частоты микропроцессора в МГц. Для подсчета количества тактов процессора применить команду RDTSC (код операции 0F31h).
РЕШЕНИЕ.
Команда RDTSC (Read Time Stamp Counter) - инструкция ассемблера для процессоров x86 читающая счетчик TSC и возвращающая в регистрах EDX:EAX 64-битное количество тактов, с момента последнего сброса процессора. Инструкция RDTSC поддерживается на платформе .386 и выше.
Надо решить, какой компилятор ассемблера выбрать для реализации этой задачи. Самые популярные из них: MASM, TASM, FASM, NASM. Данную задачу я буду писать на MASM32, как самом современном компиляторе ассемблера, на котором легко компилировать программы для Windows.
Теперь о структуре программы. Вот «скелет» стандартной программы, которая будет выводить всплывающее окно с каким-либо сообщением. В нашем случае во всплывающем окне будет выводиться сообщение о тактовой частоте процессора. Для вывода этого окна мы будем пользоваться функцией MessageBox:
.386
.model flat, stdcall
option casemap :none
include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\masm32.inc
include \MASM32\INCLUDE\gdi32.inc
include \MASM32\INCLUDE\user32.inc
include \MASM32\INCLUDE\kernel32.inc
includelib \MASM32\LIB\masm32.lib
includelib \MASM32\LIB\gdi32.lib
includelib \MASM32\LIB\user32.lib
includelib \MASM32\LIB\kernel32.lib
.data
message db "поле сообщения",0 ;переменная с сообщением
mestitle db " заголовок окна ",0 ;переменная с заголовком
.code
start:
invoke MessageBox,0,ADDR message,ADDR mestitle,MB_OK ;выводим сообщение
invoke ExitProcess,0 ;завершаем программу
end start
.386 - это директива ассемблера, определяющая набор инструкций процессора, которые могут быть использованы в программе. По умолчанию транслятор полагает, что программа пишется для процессора 8086 и сопроцессора 8087. Для приложений win32 необходимо указывать либо .386, либо выше (486, 586, 686) - в зависимости от того, собираемся ли мы использовать возможности, предоставляемые процессорами (сопроцессорами) последующих поколений или нет.
.model flat, stdcall. Первый параметр - это модель памяти. Под Windows же у нас есть одна-единственная модель памяти - flat, позволяющая нашей программе благодаря страничной адресации легко и просто работать с 4 Гб виртуальной несегментированной памяти.
Второй же параметр - stdcall - указывает на так называемое соглашение о вызове процедур. При программировании под win32 на макроассемблере нужно использовать соглашение stdcall.
.data – раздел, где объявляются переменные уже имеющие какое то значение, (инициализированные данные).
.code – раздел, где расположен код программы, то есть последовательность инструкций, которые должен выполнить компьютер.
Include – директива ассемблеру включить в текст программы, текст, хранящийся в указанном файле.
Includelib - эта директива передается компоновщику и сообщает, что наша программа должна быть слинкована с указанной библиотекой. Библиотека представляет собой некоторое количество готовых к употреблению процедур.
Invoke – команда, с помощью которой вызываются все API-функции. API-функции (Application Programming Interface — Интерфейс Программирования Приложений) обычно достаточно универсальны.
4
ОБЩИЙ ТЕКСТ ПРОГРАММЫ
.586
.model flat, stdcall
option casemap :none
include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\kernel32.inc
include \MASM32\INCLUDE\shell32.inc
include \MASM32\INCLUDE\masm32.inc
include \masm32\include\user32.inc
includelib \MASM32\LIB\kernel32.lib
includelib \MASM32\LIB\shell32.lib
includelib \masm32\lib\user32.lib
.data
capt db "RDTSC",0 ;заголовок окна
digEAX dd ? ;переменная
buf1 dd ? ;символьная строка числа
frmt db "%u",0 ;выводим значение в десятичной системе
.code
start:
rdtsc ;инструкция Read Time-Stamp Counter, в результате выполнения этой инструкции в регистрах EDX:EAX будет содержаться 64-битное количество тактов с момента последнего сброса процессора
mov esi,eax;перешлем эти данные из EAX в ESI для сравнения
mov edi,edx;то же самое
push 1000 ;эти 3 строки обеспечивают
call Sleep ;задержку работы процессора
push 0 ;на 1 секунду
rdtsc ;опять считаем счетчик TSC, в нем будет на то количество тактов больше, сколько процессор успевает выдать за 1 секунду
cmp edx,edi;сравниваем содержимое двух регистров
jb start ;переход на метку start если содержимое esi как число превышает содержимое eax (переход через ноль)
sub eax,esi;из eax вычитаем esi и результат помещаем в eax, таким образом мы узнаем сколько тактов процессор сделал за секунду
sbb edx,edi;то же самое с младшей тетрадой
mov ebx,1000000;переводим из Гц в МГц
div ebx ; делим содержимое EAX на содержимое EBX и результат в EAX
mov digEAX,eax
i
5
invoke MessageBox,0,addr buf1,addr capt,0;выводим этот символ в окно сообщения
push 0
call ExitProcess ;вызов процедуры конец процесса,процедура находится в одной из подключаемых библиотек
end start
6