8086有时间限制的编程

时间:2018-12-29 14:05:54

标签: assembly x86 emu8086

我有一个程序可以在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 :(得分:5)

因为您使用int 1Ah,所以我假设“ 8086”表示“ PC兼容”(有几台使用8086 CPU的计算机与PC不兼容)。

理论背景

在这种情况下,您可能会钩住硬件中断IRQ 0,它是CPU端的软件中断#8:

在与PC兼容的系统上,计时器将在某个计时器间隔内触发一次计时器中断(IRQ 0)。这就像软件中的int 8指令。

默认情况下,计时器的频率配置为18.2 Hz,因此int 8在10秒内将被调用182次,在120秒内将被调用2184次。

一条中断指令(int)将6个字节(标志,CS和IP)压入堆栈,然后跳转到存储在该地址的 far 地址(segment:offset) 0:(4*n)

示例:如果将0x1234存储在地址0:0x20并将0x5678存储在地址0:0x22,则int 8指令将跳转到地址{{1 }}。

进入中断例程后,堆栈(0x5678:0x1234)的前4个字节包含要在中断后执行的下一条指令的远端地址;该地址可以修改。

障碍物

请注意,当ss:sp指令禁止中断时,硬件将无法执行任何中断。在这种情况下,您将没有机会限制程序时间。

另一个问题可能是DOS和BIOS调用:

如果在BIOS调用(例如cli)或DOS调用(int 10h)内达到了120秒,并且中断了程序,则可能会使整个操作系统崩溃!

示例代码

还请注意,我通常使用GNU汇编器,它具有不同的语法。因此,也许我的示例中的某些行需要进行一些修改,因为您的汇编程序会识别语法错误。

int 21h

答案 1 :(得分:0)

我按如下所示编辑了程序,现在就可以像我想要的那样工作。谢谢。

  

我的程序生成一个随机数并对其进行一些操作并提供一些输出。

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