8086 Программирование с ограничением по времени - PullRequest
0 голосов
/ 29 декабря 2018

У меня есть программа, которая четко выполняет некоторые задачи в 8086 году, и я хочу добавить ограничение по времени для моей программы.Если моя программа не выполняет все задачи в течение 120 секунд, то программа должна быть остановлена. Как я могу это сделать?

Моя программа генерирует случайное число, выполняет с ним некоторые операции и выдает некоторые выходные данные.

org 100h 

;CALL TIMER_DISPLAY

GO:
MOV AL,0
MOV ROW,AL
CALL COORDINATE
CALL CLEAR_SCREEN
CALL RANDOM_NUMBER
MOV AL,R
AND AL,5
MOV KEY,AL   
MUL R
ADD AL,5
MOV DL,5
DIV DL
MOV KEY1,AH
CMP KEY1,0
JNE GO
LEA BX,M1
CALL DISPLAY_MESSAGE

MOV AL,KEY
OR AL,R
MOV KEY2,AL
CMP KEY2,0
JE GO
CALL COORDINATE
LEA BX,M2
CALL DISPLAY_MESSAGE

MOV AL,KEY
ADD AL,R
SAR AL,2
MOV KEY3,AL
CMP KEY3,0
JE GO 
CALL COORDINATE
LEA BX,M3
CALL DISPLAY_MESSAGE

MOV AL,KEY
XOR AL,R
MOV KEY4,AL
CMP KEY4,0
JE GO 
CALL COORDINATE
LEA BX,M4
CALL DISPLAY_MESSAGE

MOV AL,KEY
MOV DL,R
MUL DL
MOV KEY5,AL
CMP KEY5,0
JE GO   
CALL COORDINATE
LEA BX,M5
CALL DISPLAY_MESSAGE

ret

M1 DB 'LOCK 1 WAS OPENED', '$' 
M2 DB 'LOCK 2 WAS OPENED', '$'
M3 DB 'LOCK 3 WAS OPENED', '$'
M4 DB 'LOCK 4 WAS OPENED', '$'
M5 DB 'LOCK 5 WAS OPENED AND I AM OUT ', 01, '$' 

R DB ?

KEY DB ?

KEY1 DB ? 
KEY2 DB ?
KEY3 DB ?
KEY4 DB ?
KEY5 DB ?

ROW DB 0

Здесь есть процедура для генерации случайных чисел

; -- RANDOM NUMBER GENERATION PROCEDURE --
RANDOM_NUMBER PROC

MOV AH,00H ; INTERRUPTS TO GET SYSTEM TIME        
INT 1AH ; CX:DX NOW HOLD NUMBER OF CLOCK TICKS

MOV AX,DX
XOR DX,DX
MOV CX,10    
DIV CX
MOV R,DL   

MOV AX,0

RET
RANDOM_NUMBER ENDP

Процедуры для установки координат, отображения сообщений и очистки экрана.

; -- DISPLAY MESSAGE --
DISPLAY_MESSAGE PROC

MOV AL,0 
MOV AH,09H
MOV DX,BX
INT 21H

RET
DISPLAY_MESSAGE ENDP

; -- SET COORDINATE --
COORDINATE PROC

MOV AH,2H
MOV BH,0            
MOV DH,ROW
MOV DL,0
INT 10H

INC ROW

RET
COORDINATE ENDP

; -- CLEAR SCREEN --
CLEAR_SCREEN PROC

MOV AH,7        
MOV AL,0        
MOV CX,0        
MOV DX,184FH    
MOV BH,7        
INT 10H      

RET
CLEAR_SCREEN ENDP

Процедуры вызова дисплея таймера и его синхронизации с реальным временем.

; -- TIMER DISPLAY --
TIMER_DISPLAY PROC

#START=LED_DISPLAY.EXE#
;#MAKE_BIN#   
NAME "TIMER"

MOV AX,120
OUT 199,AX

X1: 
CALL SYNCHRONIZE_TIMER_DISPLAY
DEC AX
OUT 199,AX
CMP AX,0
JG X1

HLT

RET
TIMER_DISPLAY ENDP

; -- SYNCHRONIZE TIMER DISPLAY --
SYNCHRONIZE_TIMER_DISPLAY PROC

PUSH AX 

MOV CX, 0FH
MOV DX, 4240H
MOV AH, 86H
INT 15H

POP AX

RET
SYNCHRONIZE_TIMER_DISPLAY ENDP

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Я отредактировал свою программу, как показано ниже, и она работает так, как я хочу сейчас.Спасибо.

Моя программа генерирует случайное число, выполняет над ним некоторые операции и выдает несколько выходных данных.

org 100h 

#START=LED_DISPLAY.EXE#
;#MAKE_BIN#   
NAME "TIMER"

MOV AX,SECOND
OUT 199,AX


GO:
CALL TIMER_DISPLAY
MOV AL,0
MOV ROW,AL
CALL COORDINATE
CALL CLEAR_SCREEN
CALL RANDOM_NUMBER
MOV AL,R
AND AL,5
MOV KEY,AL   
MUL R
ADD AL,5
MOV DL,5
DIV DL
MOV KEY1,AH
CMP KEY1,0
JNE GO
LEA BX,M1
CALL DISPLAY_MESSAGE

MOV AL,KEY
OR AL,R
MOV KEY2,AL
CMP KEY2,0
JE GO
CALL COORDINATE
LEA BX,M2
CALL DISPLAY_MESSAGE

MOV AL,KEY
ADD AL,R
SAR AL,2
MOV KEY3,AL
CMP KEY3,0
JE GO 
CALL COORDINATE
LEA BX,M3
CALL DISPLAY_MESSAGE

MOV AL,KEY
XOR AL,R
MOV KEY4,AL
CMP KEY4,0
JE GO 
CALL COORDINATE
LEA BX,M4
CALL DISPLAY_MESSAGE

MOV AL,KEY
MOV DL,R
MUL DL
MOV KEY5,AL
CMP KEY5,0
JE GO   
CALL COORDINATE
LEA BX,M5
CALL DISPLAY_MESSAGE

ret

M1 DB 'LOCK 1 WAS OPENED', '$' 
M2 DB 'LOCK 2 WAS OPENED', '$'
M3 DB 'LOCK 3 WAS OPENED', '$'
M4 DB 'LOCK 4 WAS OPENED', '$'
M5 DB 'LOCK 5 WAS OPENED AND I AM OUT ', 01, '$' 

R DB ?

KEY DB ?

KEY1 DB ? 
KEY2 DB ?
KEY3 DB ?
KEY4 DB ?
KEY5 DB ?

ROW DB 0

SECOND DW 120

Здесь есть процедура длягенерировать случайные числа

; -- RANDOM NUMBER GENERATION PROCEDURE --
RANDOM_NUMBER PROC

MOV AH,00H ; INTERRUPTS TO GET SYSTEM TIME        
INT 1AH ; CX:DX NOW HOLD NUMBER OF CLOCK TICKS

MOV AX,DX
XOR DX,DX
MOV CX,10    
DIV CX
MOV R,DL   

MOV AX,0

RET
RANDOM_NUMBER ENDP

Процедуры для установки координат, отображения сообщений и очистки экрана.

; -- DISPLAY MESSAGE --
DISPLAY_MESSAGE PROC

MOV AL,0 
MOV AH,09H
MOV DX,BX
INT 21H

RET
DISPLAY_MESSAGE ENDP

; -- SET COORDINATE --
COORDINATE PROC

MOV AH,2H
MOV BH,0            
MOV DH,ROW
MOV DL,0
INT 10H

INC ROW

RET
COORDINATE ENDP

; -- CLEAR SCREEN --
CLEAR_SCREEN PROC

MOV AH,7
MOV AL,0        
MOV CX,0        
MOV DX,184FH    
MOV BH,7        
INT 10H      

RET
CLEAR_SCREEN ENDP

Процедуры для вызова отображения таймера исинхронизировать его с реальным временем.

; -- TIMER DISPLAY --
TIMER_DISPLAY PROC

DEC SECOND
MOV AX,SECOND
CMP AX,0
JE X1

CALL SYNCHRONIZE_TIMER_DISPLAY
OUT 199,AX
JMP EXIT

X1:
CALL SYNCHRONIZE_TIMER_DISPLAY
OUT 199,AX    
HLT

EXIT:


RET
TIMER_DISPLAY ENDP

; -- SYNCHRONIZE TIMER DISPLAY --
SYNCHRONIZE_TIMER_DISPLAY PROC

PUSH AX 

MOV CX, 0FH
MOV DX, 4240H
MOV AH, 86H
INT 15H

POP AX

RET
SYNCHRONIZE_TIMER_DISPLAY ENDP
0 голосов
/ 29 декабря 2018

Поскольку вы используете int 1Ah, я предполагаю, что «8086» означает «совместимый с ПК» (есть несколько компьютеров, использующих ЦП 8086, не совместимых с ПК).

Теоретический фон

В этом случае вы можете перехватить аппаратное прерывание IRQ 0, которое является программным прерыванием № 8 на стороне процессора:

В системе, совместимой с ПК, таймер вызовет прерывание таймера (IRQ 0) один разв некотором интервале таймера.Это похоже на инструкцию int 8 в программном обеспечении.

По умолчанию таймер настроен на частоту 18,2 Гц, поэтому int 8 будет вызываться 182 раза за 10 секунд или 2184 раза за 120 секунд.

Команда прерывания (int) помещает в стек 6 байтов (флаги, CS и IP) и затем переходит к адресу far (сегмент: смещение), сохраненному по адресу 0:(4*n).

Пример: если 0x1234 хранится по адресу 0:0x20, а 0x5678 хранится по адресу 0:0x22, инструкция int 8 перейдет к адресу 0x5678:0x1234.

Когда вводится процедура прерывания, первые 4 байта в стеке (ss:sp) содержат дальний адрес следующей инструкции, которая должна быть выполнена после прерывания;этот адрес может быть изменен.

Препятствия

Обратите внимание, что аппаратное обеспечение не может выполнять никаких прерываний, когда прерывания отключены инструкцией cli.В этом случае у вас нет шансов ограничить время вашей программы.

Другая проблема может быть вызовами DOS и BIOS:

Если в вызове BIOS достигнут 120 секунд (например, int 10h) или даже вызов DOS (int 21h), и вы прервете свою программу, вы можете привести к сбою всей операционной системы!

Пример кода

Обратите также вниманиечто я обычно использую GNU ассемблер, который имеет другой синтаксис.Поэтому, возможно, некоторые строки в моем примере нужно немного изменить, потому что ваш ассемблер распознает синтаксическую ошибку.

install:
  ; Remember the location of the original stack
  mov origStack, sp
  mov origStack+2, ss
  ; First we copy the original address of the "int 8" interrupt
  ; to the variable "origAddress"
  mov ax, 0
  mov es, ax
  mov ax, [es:20h]
  mov origAddress, ax
  mov ax, [es:22h]
  mov origAddress+2, ax
  ; We disable hardware interrupt generation
  ; This ensures that "int 8" cannot be generated between the
  ; next two instructions when [0:20h] already contains the
  ; new value but [0:22h] still contains the old one (so the
  ; combination of [0:20h] and [0:22h] is invalid)
  cli
  ; We write the address of our handler to 0:0x20
  mov word ptr [es:20h], offset hookHandler
  mov [es:22h], cs
  ; Now we can enable interrupt generation again
  sti

  ; Actually perform the program
  ...

  ; Uninstall the interrupt hook
  cli
  call uninstallHook
  ; The program finishes normally
  ...

; If the program took longer than 120s, we get here!
timeoutCode:
  cli
  ; Ensure DS contains the correct value
  push cs
  pop ds
  ; Restore the original stack
  lss sp, origStack
  ; Uninstall the hook
  call uninstallHook
  ; The program finishes due to a timeout
  ...

uninstallHook:
  ; Uninstall the hook; note: "cli" has already been called!
  mov ax, 0
  mov es, ax
  mov ax, origAddress
  mov [es:20h], ax
  mov ax, origAddress+2
  mov [es:22h], ax
  sti
  ret

; The actual handler is called 182 times in 10 seconds
; Note that a handler must not modify any registers but
; it must "push" all registers that it modifies and
; restore the original values using "pop"
hookHandler:
  ; Decrement the variable "timeout"
  dec word ptr [cs:timeout]
  ; Is it zero?
  jnz notZero
  ; It is zero; replace the address of the instruction
  ; that is executed after the interrupt by "timeoutCode"
  push bp
  mov bp,sp
  mov word ptr [ss:bp+2], timeoutCode
  mov word ptr [ss:bp+4], cs ; (segment of timeoutCode)
  pop bp
notZero:
  ; Jump to the original handler of the BIOS which will
  ; do the rest (e.g. handle the interrupt controller)
  jmp dword ptr [cs:origAddress]

origAddress DW 0,0
origStack   DW 0,0
timeout     DW 2184
...