	 include sysp.inc

	.MODEL tiny
	.CODE

	PUBLIC ntrace87


;==========================================
; Процедура выводит на экран содержимое
; всех регистров центрального процессора
; и сопроцессора. Затем она ожидает нажатия на
; любую клавишу.
; После возвращения из процедуры
; все регистры восстанавливаются, в том
; числе регистры сопроцессора.

ntrace87 proc near

; Сохраняем в стеке регистры,
; содержимое которых будет изменяться

     pushf
     push ax
     push bx
     push cx
     push dx
     push ds
     push bp

     mov bp,sp

	  push cs
	  pop ds

; Сохраняем полное состояние сопроцессора

	  fsave  cs:regs_87

; Выводим сообщение об останове

	  mov dx,offset cs:trace_msg
	  @@out_str

; Выводим содержимое всех регистров

	  mov ax,cs        ; cs
     call Print_word
	  @@out_ch ':'
     mov ax,[bp]+14   ; ip
     call Print_word

	  @@out_ch 13,10,13,10,'A','X','='
     mov ax,[bp]+10
     call Print_word

	  @@out_ch ' ','B','X','='
     mov ax,[bp]+8
     call Print_word

	  @@out_ch ' ','C','X','='
     mov ax,[bp]+6
     call Print_word

	  @@out_ch ' ','D','X','='
     mov ax,[bp]+4
     call Print_word

	  @@out_ch ' ','S','P','='
     mov ax,bp
	  add ax,16
     call Print_word

	  @@out_ch ' ','B','P','='
     mov ax,[bp]
     call Print_word

	  @@out_ch ' ','S','I','='
     mov ax,si
     call Print_word

	  @@out_ch ' ','D','I','='
     mov ax,di
     call Print_word

	  @@out_ch 13,10,'D','S','='
     mov ax,[bp]+2
     call Print_word

	  @@out_ch ' ','E','S','='
     mov ax,es
     call Print_word

	  @@out_ch ' ','S','S','='
     mov ax,ss
     call Print_word

	  @@out_ch ' ','F','='
     mov ax,[bp]+12
     call Print_word

; Выводим содержимое регистров сопроцессора

	  lea dx,cs:r87_msg
	  @@out_str

; Выводим содержимое управляющего регистра

	  @@out_ch 'C','N','T','R','='

	  mov ax, cs:regs_87.cr
	  call Print_word

; Выводим содержимое регистра состояния

	  @@out_ch ' ','S','T','A','T','E','='

	  mov ax, cs:regs_87.sr
	  call Print_word

; Выводим содержимое регситра тегов

	  @@out_ch ' ','T','A','G','='

	  mov ax, cs:regs_87.tg
	  call Print_word

; Выводим содержимое указателя адреса

	  @@out_ch ' ','C','M','D','A','D','R','='

	  mov ax, cs:regs_87.cmdhi
	  and  ah, 0f0h
	  mov al, ah
	  mov cl, 4
	  ror al, cl
	  call Print_byte
	  mov ax, cs:regs_87.cmdlo
	  call Print_word
	  @@out_ch ' '

; Выводим содержимое указателя операнда

	  @@out_ch ' ','O','P','R','A','D','R','='

	  mov ax, cs:regs_87.oprhi
	  and  ah, 0f0h
	  mov al, ah
	  mov cl, 4
	  ror al, cl
	  call Print_byte
	  mov ax, cs:regs_87.oprlo
	  call Print_word

; Выводим содержимое непустых численных регистров

	  lea dx,cs:nr_msg
	  @@out_str

	  mov cx, 8              ; количество регистров - 8
	  mov dx, 0              ; индекс текущего регистра
	  mov bx, cs:regs_87.tg  ; содержимое регистра тегов

; Цикл по стеку численных регистров

nreg_loop:

; Проверяем поле регистра тегов, соответствующее
; текущему обрабатываемому численному регистру

	  mov ax, bx
	  and ax, 0c000h
	  cmp ax, 0c000h

; Если это поле равно 11B, считаем, что данный
; численный регистр пуст, переходим к следующему

	  je continue

; Выводим на экран содержимое численного регистра

	  call Print_numreg

continue:

; Сдвигаем содержимое регистра тегов для
; обработки поля, соответствующего следующему
; регистру.

	  rol bx, 1
	  rol bx, 1
	  inc dx       ; увеличиваем индекс текущего регистра

	  loop nreg_loop

	  lea dx,cs:hit_msg
	  @@out_str

; Ожидаем нажатия на любую клавишу

	  mov ax,0
     int 16h

; Восстанавливаем содержимое регистров

	  frstor  cs:regs_87

     pop bp
     pop ds
     pop dx
     pop cx
     pop bx
     pop ax
     popf

     ret

trace_msg db 13,10,'>---- BREAK ----> At address ','$'
hit_msg db 13,10,'Hit any key...','$'
r87_msg db 13,10,13,10,'Coprocessor state:',13,10,'$'
nr_msg db 13,10,'Numeric Registers:',13,10,'$'

regs_87 db 94 dup(?)
ten db 10

ntrace87 endp

;==========================================
; Процедура выводит на экран содержимое
; численного регистра с номером, заданным
; в регистре al

Print_numreg proc near
	  push cx
	  push bx

; Выводим обозначение численного регистра

	  push dx
	  @@out_ch 'S','T','('
	  pop dx
	  mov al, dl
	  call Print_byte
	  push dx
	  @@out_ch ')','='
	  pop dx

; Выводим содержимое численного регистра в
; шестнадцатеричном формате

	  mov cx, 10    ; счетчик байтов в числе с
						 ; расширенной точностью
	  mov bp, 10    ; первоначальное смещение
						 ; к старшему байту числа

; Смещение к полю первого численного регистра
; в области сохранения

	  mov bx, offset cs:regs_87.st0

; Вычисляем смещение старшего байта численного
; регистра, номер которого задан в регистре DX

	  mov ax, dx
	  imul cs:ten
	  add bx, ax
	  dec bx

; Выводим в цикле 10 байтов числа

pr_lp:
	  push bx

	  add bx, bp
	  mov al, cs:[bx]
	  call Print_byte
	  pop bx

	  dec bp
	  loop pr_lp

	  push dx
	  @@out_ch 13,10
	  pop dx

	  pop bx
	  pop cx
	  ret

Print_numreg endp


;==========================================
; Процедура выводит на экран содержимое AL

Print_byte proc near

	  push ax
	  push bx
	  push dx

	  call Byte_to_hex
	  mov bx,dx
	  @@out_ch bh
	  @@out_ch bl

	  pop dx
	  pop bx
	  pop ax
	  ret
Print_byte endp

;==========================================
; Процедура выводит на экран содержимое AX

Print_word proc near

	  push ax
     push bx
     push dx

	  push ax
	  mov cl,8
	  rol ax,cl
	  call Byte_to_hex
	  mov bx,dx
	  @@out_ch bh
	  @@out_ch bl

	  pop ax
     call Byte_to_hex
     mov bx,dx
	  @@out_ch bh
	  @@out_ch bl

     pop dx
     pop bx
     pop ax
     ret
Print_word endp

Byte_to_hex proc near
;--------------------
; al - input byte
; dx - output hex
;--------------------
     push ds
     push cx
     push bx

     lea bx,tabl
     mov dx,cs
     mov ds,dx

     push ax
     and al,0fh
     xlat
     mov dl,al

     pop ax
     mov cl,4
     shr al,cl
     xlat
     mov dh,al

     pop bx
     pop cx
     pop ds
     ret

tabl db '0123456789ABCDEF'
Byte_to_hex endp

     end
