Поиск:

Ответ в темуСоздание новой темы Создание опроса
> вопрос к гуру по прерываниям - не 1 а целых 2 :-) 
:(
    Опции темы
Yarikon
  Дата 7.1.2004, 00:47 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Мужики, спасайтею. Написал тут 2 проги на ASMе (TASM 1.0) а они компилироваться не хотят - ошибки выдают confused.gif .
Помощь ваша нужна просто по-зарез, горю - готов уже повесится...PLS HELP ME butbut.gif
_____________________________________________________________________________________________________________
1)каждую секунду программа проверяет биты в регистрах AX, BX, CX, DX.
для сохранения данных создан массив размером 64 dw, один word для каждого бита.
каждую секунду программа проверяет биты в каждом из выше перечисленных регистров,
если бит равен единице то ячеика отведенная для этого бита в массиве увеличивается на один. Программа должна работать на протяжение часа.

Код

.MODEL LARGE

.DATA

 ; Screen messages to display to the user.

prompt_string   DB 'Please enter the time interval in seconds,',13,10
                DB 'no more than 3600 seconds ( an hour ): $'

error_string    DB 13,10,10,'Input error! The interval'
                DB ' set to 60 seconds ( a minute ).',13,10,'$'

report_string   DB 13,10,'Final report:',13,10,'$'

ax_string       DB 13,10,'AX:$'
bx_string       DB 13,10,'BX:$'
cx_string       DB 13,10,'CX:$'
dx_string       DB 13,10,'DX:$'

finish_string   DB 13,10,10,'Finished.',13,10,'$'

 ; Three constants for technical needs.
hundred         DW 100
ten             DW 10
const182        DW 182

;=============================================================================
;=============================================================================

.CODE

;--------------------------------------------------------------------------
; 1. Declarations of variables to handle interrupt 8 and counting.
;--------------------------------------------------------------------------

                                ; Array of counters initialized by zeroes:
count_array     DW 16 DUP (0)   ; 16 counters for 16 bits of AX ,
                DW 16 DUP (0)   ; 16          for            BX ,
                DW 16 DUP (0)   ; 16          for            CX ,
                DW 16 DUP (0)   ; 16          for            DX .

n_ticks           DW 0           ; Ticks from the beginning, initially zero.
max_ticks       DW (?)         ; Ticks in the requested time interval.

oldint8_seg     DW (?)        ; For old ISR 8 address.
oldint8_offset  DW (?)        ;

flag            DB 1               ; 1 - the counting continues, 0 - finished.

;--------------------------------------------------------------------------
; 2. 'analyse_word' - extract bits from the word given in AX, increment
;    corresponding counters in count_array from count_array[SI] (SI given).
;--------------------------------------------------------------------------

analyse_word PROC FAR        ; ( Arguments: AX - the word to analyse,
                             ;   SI - the index of the first counter. )

  PUSH BX                    ;
  PUSH CX                    ; Preserve registers.
  PUSH DX                    
                             ; BX will be the mask for extracting bits,
  MOV BX, 1                  ; starts from 0000000000000001b.

  MOV CX, 16                 ; There are 16 bits in the word.

 analyse_loop:               ; Loop over all bits:
                             ;
     MOV DX, AX              ; Copy the word to DX.
     AND DX, BX              ; Extract a bit. DX becomes 0 iff the bit
     CMP DX, 0               ;   matching '1' in the mask is 0; if so
     JE next_bit             ;   then go to the next bit...
                             ;    
     MOV DX, count_array[SI] ;     ... otherwise:
     INC DX                  ;   increment the corresponding counter.
     MOV count_array[SI], DX ;
                             ;
    next_bit:                ; Go to the next bit:
     ADD SI, 2               ; a) Move to the next counter ( 2 bytes ).
     SHL BX, 1               ; b) Move '1' in the mask one position to left.
   LOOP analyse_loop         ; c) Do next iteration.
                             
  POP DX                     ;
  POP CX                     ; Restore registers...
  POP BX                     ;
  RET                        ;   ... and return.
analyse_word ENDP


;--------------------------------------------------------------------------
; 3. 'newint8' routine - at each clock tick analyse bits in AX,BX,CX,DX ,
;    increment n_ticks, signal when the time interval elapses.
;--------------------------------------------------------------------------

newint8 PROC FAR

  PUSH ES                   ;
  PUSH DI                   ;
  PUSH SI                   ;
  PUSH DX                   ; Preserve registers.
  PUSH CX                   ;
  PUSH BX                   ;
  PUSH AX                   ;

  MOV AX, oldint8_seg       ;
  MOV ES, AX                ;
  MOV BX, oldint8_offset    ; Call old ISR 8.
  PUSHF                     ;
  CALL FAR PTR ES:BX        ;

  MOV AX, n_ticks           ;
  INC AX                    ; Increment n_ticks.
  CMP AX, max_ticks         ; If max_ticks reached...
  JG stop_counting          ;    ... then stop the counting.

 continue_counting:         ; otherwise:
     MOV n_ticks, AX        ;  a) Save the incremented value.
     MOV SI, 0              ;  b) The first counter will be No 0.
     POP AX                 ;  c) Get the original value of AX for analysis.
     MOV DI, AX             ;  d) Preserve it in DI.
     CALL analyse_word      ;  e) Analyse AX.
                            ;
     POP AX                 ;  f) Get the original value of BX for analysis.
     CALL analyse_word      ;  g) Analyse it. ( The loop in 'analyse_word'
                            ;                   advanced SI exactly to the
                            ;                   counters corresponding BX. )
     MOV BX, AX             ;  h) Restore it to BX.
                            ;
     POP AX                 ;  i) Get the original value of CX for analysis.
     CALL analyse_word      ;  j) Analyse it.
     MOV CX, AX             ;  k) Restore it to CX.
                            ;
     POP AX                 ;  l) Get the original value of DX for analysis.
     CALL analyse_word      ;  m) Analyse it.
     MOV DX, AX             ;  n) Restore it to DX.
                            ;
     MOV AX, DI             ;  o) Restore the original value of AX.
     JMP finish8            ;  p) Finish ISR 8.

 stop_counting:             ; When the counting stops:
     XOR AX, AX             ;
     MOV ES, AX             ;
     MOV AX, oldint8_offset ;  a) Restore old ISR addresses in the IV.
     MOV BX, oldint8_seg    ;
     CLI                    ;
     MOV ES:[8*4], AX       ;
     MOV ES:[8*4+2], BX     ;
     STI                    ;
     XOR AL, AL             ;  b) Zero the flag to signal the main program
     MOV flag, AL           ;     that the counting finished.
     POP AX                 ;
     POP BX                 ;  c) Restore AX,BX,CX,DX .
     POP CX                 ;
     POP DX                 ;
                             
 finish8:                   ; The common end:
  POP SI                    ;
  POP DI                    ; restore SI,DI,ES ...
  POP ES                    ;
  IRET                      ;    ... and return.

newint8 ENDP


;--------------------------------------------------------------------------
; 4. 'display_number' - display an integer ( a word ) in AX on the screen.
;--------------------------------------------------------------------------

display_number PROC FAR; ( Argument: AX - the value to display. )

  PUSH DX              ; Preserve registers.
  PUSH BX              ;

 output_loop:          ;
     XOR DX, DX        ; Zero DX for correct division.
     DIV ten           ; Extract the last decimal digit of AX:
                       ;  AX gets the integer part of (AX/10),
                       ;  DX ( actually DL ) gets the residual.
     MOV BX, AX        ; Preserve the integer part in BX.
     ADD DL, '0'       ; Actually DL holds the last digit; convert it to
                       ; ASCII code of the corresponding character...
     MOV AH, 2         ;  
     INT 21h           ;   ... and display it on the screen.
                       ;
     MOV AX, BX        ; Restore the integer part for the next iteration.
     CMP AX, 0         ; If there are still digits in the number...
     JNE output_loop   ;   ... then go to the next iteration.

  POP BX               ; Restore registers...
  POP DX               ;
  RET                  ;      ... and return.
display_number ENDP


;--------------------------------------------------------------------------
; 5. 'report' - for each bit in AX,BX,CX,DX display the percent of clock
;    ticks in which it was 1.
;--------------------------------------------------------------------------

report PROC FAR
  PUSH AX                     ;
  PUSH SI                     ; Preserve registers.
  PUSH CX                     ;
  PUSH DX                     ;
  PUSH DS                     ;

  MOV SI, 0                   ; SI will be an index in count_array,
                              ; starts from zero.

  MOV DX, SEG report_string   ;
  MOV DS, DX                  ; Display 'report' string for the user.
  MOV DX, OFFSET report_string;
  MOV AX, 9                   ;
  INT 21h                     ;

  MOV DX, SEG ax_string       ;
  MOV DS, DX                  ; Display 'AX:' string for the user.
  MOV DX, OFFSET ax_string    ;
  MOV AX, 9                   ;
  INT 21h                     ;
  MOV CX, 16                  ; There are 16 bits in AX.
 display_ax_loop:             ;
     MOV DL, ' '              ; Space to separate between numbers.
     MOV AH, 2                ;
     INT 21h                  ;
     MOV AX, count_array[SI]  ; Get the value n of a counter.
     MUL hundred     ; DX:AX<-100*n        : Convert to percents:
     DIV max_ticks   ; AX<-100*n/max_ticks : (percent among all ticks) =
                              ;             100*(counter value)/(num.ticks).
     CALL display_number      ; Display on the screen.
     ADD SI, 2                ; Move to the next counter ( 2 bytes ).
    LOOP display_ax_loop      ;

  MOV DX, SEG bx_string       ; The same things for BX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET bx_string    ;
  MOV AX, 9                   ;
  INT 21h                     ;
  MOV CX, 16                  ;
 display_bx_loop:             ;
     MOV DL, ' '              ;
     MOV AH, 2                ;
     INT 21h                  ;
     MOV AX, count_array[SI]  ; ( In the previous loop SI arrived exactly
     MUL hundred              ;   to the counters that hold BX statistics. )
     DIV n_ticks              ;
     CALL display_number      ;
     ADD SI, 2                ;
    LOOP display_bx_loop      ;

  MOV DX, SEG cx_string       ; The same things for CX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET cx_string    ;
  MOV AX, 9                   ;
  INT 21h                     ;
  MOV CX, 16                  ;
 display_cx_loop:             ;
     MOV DL, ' '              ;
     MOV AH, 2                ;
     INT 21h                  ;
     MOV AX, count_array[SI]  ;
     MUL hundred              ;
     DIV n_ticks              ;
     CALL display_number      ;
     ADD SI, 2                ;
    LOOP display_cx_loop      ;

  MOV DX, SEG dx_string       ; The same things for DX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET dx_string    ;
  MOV AX, 9                   ;
  INT 21h                     ;
  MOV CX, 16                  ;
 display_dx_loop:             ;
     MOV DL, ' '              ;
     MOV AH, 2                ;
     INT 21h                  ;
     MOV AX, count_array[SI]  ;
     MUL hundred              ;
     DIV n_ticks              ;
     CALL display_number      ;
     ADD SI, 2                ;
    LOOP display_dx_loop      ;

  POP DS                      ;
  POP DX                      ; Restore registers...
  POP CX                      ;
  POP BX                      ;
  POP AX                      ;
  RET                         ;    ... and return.
report ENDP


;--------------------------------------------------------------------------
; 6. 'input_time_interval' - the user inputs a positive integer number of
;    seconds in the requested time interval, the number returns in AX;
;    if it was not in the range 1...3600 seconds, the routine sets it to 60.
;--------------------------------------------------------------------------

input_time_interval PROC FAR   ; ( Returned value: AX - number of seconds. )

  PUSH BX                      ;
  PUSH CX                      ; Preserve registers.
  PUSH DX                      ;
  PUSH DS                      
                               ; The number will be built digit-by-digit
  XOR AX, AX                   ; in AX; starts from zero.
                               
  input_loop:                  ; Each iteration adds a digit at the end
                               ; of AX ( e.g. AX=123,input '4' -> AX=1234 )
      MOV DX, AX               ; Preserve the previous value (123) in DX.
      MOV AH, 1                ; Get the next datum from the keyboard
      INT 21h          ; AL<-'4'  ( it arrives to AL ).
      CMP AL, 13               ; If it is ENTER...
      JE end_input             ;      ... then the input ends.
                               ; Otherwise: convert the ASCII code
      ADD AL, '0'      ; AL<-4             of a digit to the digit itself
      MOV BL, AL               ; and copy it to BL...
      MOV BH, 0                ;      ... and to BX. ( BX=4 )
      MOV AX, DX               ; Restore the previous value in AX (AX<-123).
      MUL ten          ; AX<-1230
      JO input_error           ; If overflow ( number too big ) then error.
      ADD AX, BX       ; AX<-1234
      JO input_error           ; If overflow ( number too big ) then error.
     JMP input_loop            ; Otherwise go to the next iteration.

 end_input:                    ; When the input ends:
    CMP AX, 3600               ;  a) If it is too big...
    JG input_error             ;       ... then it is an error.
    CMP AX, 0                  ;  b) If the number is really positive...
    JG return_number           ;     ... then return it.

 input_error:                  ; If there was any error:
    MOV DX, SEG error_string   ;
    MOV DS, DX                 ;
    MOV DX, OFFSET error_string;
    MOV AH, 9                  ;  a) Display the error message.
    INT 21h                    ;
    MOV AX, 60                 ;  b) Set the number to be 60 seconds.

 return_number:                ; In any case:
  POP DS                       ;
  POP DX                       ; Restore registers...
  POP CX                       ;
  POP BX                       ;
  RET                          ;   ... and return ( return AX ).
input_time_interval ENDP


;--------------------------------------------------------------------------
; 7. The main program - input time interval from the user, set new ISR 8
;    that will count how many times each bit in AX,BX,CX,DX was 1 at
;    clock ticks during this interval, then display the results.
;--------------------------------------------------------------------------

main:
  MOV AX, @DATA
  MOV DS, AX
 
  MOV AX, 0                   ;
  MOV ES, AX                  ; Point to segment 0.
  MOV AX, ES:[8*4]            ;
  MOV DWORD PTR oldint8_offset; Save old ISR 8 address.
  MOV AX, ES:[8*4+2]          ;
  MOV DWORD PTR oldint8_seg   ;
 
  MOV DX, OFFSET prompt_string;
  MOV AH, 9                   ; Prompt the user to enter the time interval.
  INT 21h                     ;
  CALL input_time_interval    ; Input the time interval from the user
                              ;             ( the value t returned in AX ).
  MUL const182      ; DX:AX <- t*182   :
  DIV ten           ; AX <- t*18.2     : Convert seconds to ticks.
  MOV max_ticks, AX           ; max_ticks gets the time interval in ticks.

  MOV AX, OFFSET newint8      ;
  MOV BX, SEG newint8         ; Compute new ISR 8 address.
  CLI                         ;
  MOV ES:[8*4], AX            ; Write the new addresses to the IV.
  MOV ES:[8*4+2], BX          ;
  STI                         ; The counting starts here.
 
 waiting_loop:                ; The main program begins to wait...
    MOV AX, flag              ;
    CMP AX, 0                 ;    ... until flag=0  ( newint8 will signal
    JNE waiting_loop          ;                the end by setting flag<-0 )

  CALL report                 ; Display the results when the counting stops.

  MOV DX, OFFSET finish_string;
  MOV AH, 9                   ; Display the message 'Finished'.
  INT 21h                     ;

  MOV AH, 4Ch                 ; Terminate the program.
  INT 21h                     ; ( IV was restored in newint8. )
                               
END main




2)программа не позволяет медленно вводить данные с клавиатуры,
после каждого ввода измеряеться время до следущего ввода
если прошло больше 1.5 минуты, клавиатура блокируется, и только после нажатия enter
можно продолжить ввод данных. Программа будет измерять время до нажатие на esc.




Код

.MODEL LARGE

.DATA
           ; Screen messages for the user.

prompt_string   DB 'Please enter text.',13,10,10,'$'
                DB 'Please keep such a rate that intervals between',13,10,'$'
                DB 'each two key pressings will not be longer than',13,10,'$'
                DB '100 clock ticks.',13,10,10,'$'
                DB 'Press ESC to finish.',13,10,'$'

too_long_string DB 13,10,10,'Time too long. Keyboard locked.'
                DB ' Press ENTER to release.',13,10,10,'$'

finish_string   DB 13,10,10,'Finished.',13,10,'$'

;=============================================================================
;=============================================================================

.CODE

;--------------------------------------------------------------------------
; 1. Declarations of constants and variables to handle interrupts 8 and 9.
;--------------------------------------------------------------------------

t EQ 100                   ; Maximal number of ticks allowed.
n_ticks         DW 0       ; Ticks counter since last key pressing.

oldint8_seg     DW (?)     ; For old ISR 8 address.
oldint8_offset  DW (?)     ;

free   EQ 1                ;
locked EQ 0                ; Keyboard status.
keyboard_status DB free    ;

oldint9_seg     DW (?)     ; For old ISR 9 address.
oldint9_offset  DW (?)     ;


;--------------------------------------------------------------------------
; 2. 'newint8' routine - increment n_ticks, lock keyboard when time elapses.
;--------------------------------------------------------------------------

newint8 PROC FAR

  PUSH ES                         ;
  PUSH BX                         ; Preserve registers.
  PUSH AX                         ;

  MOV AX, oldint8_seg             ;
  MOV ES, AX                      ;
  MOV BX, oldint8_offset          ; Call old ISR 8.
  PUSHF                           ;
  CALL FAR PTR ES:BX              ;

  MOV AL, keyboard_status         ;
  CMP AL, locked                  ; If the keyboard is locked...
  JE finish8                      ;   ... then no action needed.

  MOV AX, n_ticks                 ; Increment n_ticks.
  INC AX                          ;
  CMP AX, t                       ; If the time elapsed...
  JLE time_too_long               ;   ...then go to this case.

 time_ok:                         ; If the time is OK:
    MOV n_ticks, AX               ; Save the new value of n_ticks.
    JMP finish8                   ; No more action needed.

 time_too_long:                   ; If the time elapsed:
    MOV AL, locked                ;
    MOV keyboard_status, AL       ;  a) Lock the keyboard.

    PUSH DS                       ;
    PUSH DX                       ;
    MOV AX, SEG too_long_string   ;
    MOV DS, AX                    ;
    MOV DX, OFFSET too_long_string;
    MOV AH, 9                     ;  b) Display the message 'Time too long'
    INT 21h                       ;     on the screen.
    POP DX                        ;
    POP DS                        ;

 finish8:                         ; The common end for all the cases:
  POP AX                          ;
  POP BX                          ; Restore registers...
  POP ES                          ;
  IRET                            ;    ... and return.

newint8 ENDP


;--------------------------------------------------------------------------
; 3. 'newint9' routine - start a new counting of n_ticks; if the keyboard
;    is locked then ignore key pressing but release keyboard when ENTER.
;--------------------------------------------------------------------------

newint9 PROC FAR

  PUSH AX                  ;
  PUSH BX                  ; Preserve registers.
  PUSH ES                  ;

  MOV AL, keyboard_status  ;
  CMP AX, locked           ; If the keyboard is locked...
  JE when_keyboard_locked  ;     ... then go to this case.

 when_keyboard_free:       ; If the keyboard is free:
   MOV AX, oldint9_seg     ;
   MOV ES, AX              ;
   MOV BX, oldint9_offset  ;
   PUSHF                   ;
   CALL FAR PTR ES:BX      ;  a) Call usual ISR 9.
   XOR AX, AX              ;
   MOV n_ticks, AX         ;  b) Start a new counting by zeroing n_ticks.
   JMP finish9             ;

 when_keyboard_locked:     ; If the keyboard is locked:
   MOV AH, 0               ;
   INT 16h                 ;  a) Get the next data.
   CMP AL, 13              ;  b) If it is anything but ENTER...
   JNE finish9             ;       ... then ignore it.
                           ;    Otherwise:
   XOR AX, AX              ;  c) Zero n_ticks.  
   MOV n_ticks, AX         ;      ( AH remains 0 here - for INT 16h. )
   INT 16h                 ;  d) Get ASCII 10 from the buffer.
   MOV AL, free            ;      ( ENTER generates 13,10 in the buffer. )
   MOV keyboard_status, AL ;  e) Release the keyboard.

 finish9:                  ; The common end:
  POP ES                   ;
  POP BX                   ; Restore registers...
  POP AX                   ;
  IRET                     ;    ... and return.
newint9 ENDP


;--------------------------------------------------------------------------
; 4. The main program - set new ISR 8 and 9, input text from the keyboard
;    until ESC.
;--------------------------------------------------------------------------

main:
  MOV AX, @DATA
  MOV DS, AX
 
  MOV AX, 0                   ;
  MOV ES, AX                  ; Point to segment 0.
  MOV AX, ES:[8*4]            ;
  MOV DWORD PTR oldint8_offset; Save old ISR 8 address.
  MOV AX, ES:[8*4+2]          ;
  MOV DWORD PTR oldint8_seg   ;
  MOV AX, ES:[9*4]            ;
  MOV DWORD PTR oldint9_offset; Save old ISR 9 address.
  MOV AX, ES:[9*4+2]          ;
  MOV DWORD PTR oldint9_seg   ;
 
  MOV AX, OFFSET newint8      ;
  MOV BX, SEG newint8         ; Compute new ISR 8 and 9 addresses.
  MOV CX, OFFSET newint9      ;
  MOV DX, SEG newint9         ;
  CLI                         ;
  MOV ES:[8*4], AX            ;
  MOV ES:[8*4+2], BX          ; Write the new addresses to the IV.
  MOV ES:[9*4], CX            ;
  MOV ES:[9*4+2], DX          ;
  STI                         ;
 
  MOV DX, OFFSET prompt_string;
  MOV AH, 9                   ; Prompt the user to enter text.
  INT 21h                     ;

 text_input_loop:             ;
   MOV AX, 1                  ;
   INT 21h                    ; Wait for a text input...
   CMP AL, 27                 ;      
   JNE text_input_loop        ;      ... until ESC.
 
  MOV AX, oldint8_offset      ;
  MOV BX, oldint8_seg         ;
  MOV CX, oldint9_offset      ;
  MOV DX, oldint9_seg         ;
  CLI                         ;
  MOV ES:[8*4], AX            ;
  MOV ES:[8*4+2], BX          ; Restore old ISR addresses in the IV.
  MOV ES:[9*4], CX            ;
  MOV ES:[9*4+2], DX          ;
  STI                         ;

  MOV DX, OFFSET finish_string;
  MOV AH, 9                   ; Display the message 'Finished'.
  INT 21h                     ;

  MOV AH, 4Ch                 ;
  INT 21h                     ; Terminate the program.

END main


HELP KTO MO}|{ET!!!!
  Вверх
Chingachguk
Дата 7.1.2004, 03:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: нет
Всего: 18



Держи это ... нечто. Если честно, я задолбался ошибки исправлять. Вбил для отладки 2 секунды. Потому, что функция ввода нифга не работает. Вообще все не работает... Вывод ax я таки сделал.

Цитата

.MODEL LARGE

.STACK 1000

.DATA

; Screen messages to display to the user.

prompt_string  DB 'Please enter the time interval in seconds,',13,10
                DB 'no more than 3600 seconds ( an hour ): $'

error_string    DB 13,10,10,'Input error! The interval'
                DB ' set to 60 seconds ( a minute ).',13,10,'$'

report_string  DB 13,10,'Final report:',13,10,'$'

ax_string      DB 13,10,'AX:$'
bx_string      DB 13,10,'BX:$'
cx_string      DB 13,10,'CX:$'
dx_string      DB 13,10,'DX:$'

finish_string  DB 13,10,10,'Finished.',13,10,'$'

; Three constants for technical needs.
hundred        DW 100
ten            DW 10
const182        DW 182

;=============================================================================
;=============================================================================

.CODE

;--------------------------------------------------------------------------
; 1. Declarations of variables to handle interrupt 8 and counting.
;--------------------------------------------------------------------------

                                ; Array of counters initialized by zeroes:
count_array    DW 16 DUP (0)  ; 16 counters for 16 bits of AX ,
                DW 16 DUP (0)  ; 16          for            BX ,
                DW 16 DUP (0)  ; 16          for            CX ,
                DW 16 DUP (0)  ; 16          for            DX .

n_ticks          DW 0          ; Ticks from the beginning, initially zero.
max_ticks      DW (?)        ; Ticks in the requested time interval.

; Chingachguk: change order of declaration

oldint8_offset  DW (?)        ;
oldint8_seg    DW (?)        ; For old ISR 8 address.

flag            DB 1              ; 1 - the counting continues, 0 - finished.

;--------------------------------------------------------------------------
; 2. 'analyse_word' - extract bits from the word given in AX, increment
;    corresponding counters in count_array from count_array[SI] (SI given).
;--------------------------------------------------------------------------

analyse_word PROC FAR        ; ( Arguments: AX - the word to analyse,
                            ;  SI - the index of the first counter. )

  PUSH BX                    ;
  PUSH CX                    ; Preserve registers.
  PUSH DX                   
                            ; BX will be the mask for extracting bits,
  MOV BX, 1                  ; starts from 0000000000000001b.

  MOV CX, 16                ; There are 16 bits in the word.

analyse_loop:              ; Loop over all bits:
                            ;
    MOV DX, AX              ; Copy the word to DX.
    AND DX, BX              ; Extract a bit. DX becomes 0 iff the bit
    CMP DX, 0              ;  matching '1' in the mask is 0; if so
    JE next_bit            ;  then go to the next bit...
                            ;   
    MOV DX, cs:count_array[SI] ;    ... otherwise:
    INC DX                  ;  increment the corresponding counter.
    MOV cs:count_array[SI], DX ;
                            ;
    next_bit:                ; Go to the next bit:
    ADD SI, 2              ; a) Move to the next counter ( 2 bytes ).
    SHL BX, 1              ; b) Move '1' in the mask one position to left.
  LOOP analyse_loop        ; c) Do next iteration.
                             
  POP DX                    ;
  POP CX                    ; Restore registers...
  POP BX                    ;
  RET                        ;  ... and return.
analyse_word ENDP


;--------------------------------------------------------------------------
; 3. 'newint8' routine - at each clock tick analyse bits in AX,BX,CX,DX ,
;    increment n_ticks, signal when the time interval elapses.
;--------------------------------------------------------------------------

newint8 PROC FAR

  PUSH ES                  ;
  PUSH DI                  ;
  PUSH SI                  ;
  PUSH DX                  ; Preserve registers.
  PUSH CX                  ;
  PUSH BX                  ;
  PUSH AX                  ;

; comment by Chingachguk smile.gif
;  MOV AX, oldint8_seg      ;
;  MOV ES, AX                ;
;  MOV BX, oldint8_offset    ; Call old ISR 8.
;  PUSHF                    ;
;  CALL FAR PTR ES:BX        ;
; comment by Chingachguk smile.gif

  ; new: call old int 08h
  pushf
  call dword ptr cs:oldint8_offset
 
; Chingachguk
  MOV AX, cs:n_ticks          ;
  INC AX                    ; Increment n_ticks.
  CMP AX, cs:max_ticks        ; If max_ticks reached...
  JG stop_counting          ;    ... then stop the counting.

continue_counting:        ; otherwise:
    MOV cs:n_ticks, AX        ;  a) Save the incremented value.
    MOV SI, 0              ;  b) The first counter will be No 0.
    POP AX                ;  c) Get the original value of AX for analysis.
    MOV DI, AX            ;  d) Preserve it in DI.
    CALL analyse_word      ;  e) Analyse AX.
                            ;
    POP AX                ;  f) Get the original value of BX for analysis.
    CALL analyse_word      ;  g) Analyse it. ( The loop in 'analyse_word'
                            ;                  advanced SI exactly to the
                            ;                  counters corresponding BX. )
    MOV BX, AX            ;  h) Restore it to BX.
                            ;
    POP AX                ;  i) Get the original value of CX for analysis.
    CALL analyse_word      ;  j) Analyse it.
    MOV CX, AX            ;  k) Restore it to CX.
                            ;
    POP AX                ;  l) Get the original value of DX for analysis.
    CALL analyse_word      ;  m) Analyse it.
    MOV DX, AX            ;  n) Restore it to DX.
                            ;
    MOV AX, DI            ;  o) Restore the original value of AX.
    JMP finish8            ;  p) Finish ISR 8.

stop_counting:            ; When the counting stops:
    XOR AX, AX            ;
    MOV ES, AX            ;
; Chingachguk
    MOV AX, cs:oldint8_offset ;  a) Restore old ISR addresses in the IV.
    MOV BX, cs:oldint8_seg    ;
    CLI                    ;
    MOV ES:[8*4], AX      ;
    MOV ES:[8*4+2], BX    ;
    STI                    ;
    XOR AL, AL            ;  b) Zero the flag to signal the main program
    MOV cs:flag, AL        ;    that the counting finished.
    POP AX                ;
    POP BX                ;  c) Restore AX,BX,CX,DX .
    POP CX                ;
    POP DX                ;
                           
finish8:                  ; The common end:
  POP SI                    ;
  POP DI                    ; restore SI,DI,ES ...
  POP ES                    ;
  IRET                      ;    ... and return.

newint8 ENDP


;--------------------------------------------------------------------------
; 4. 'display_number' - display an integer ( a word ) in AX on the screen.
;--------------------------------------------------------------------------

display_number PROC FAR; ( Argument: AX - the value to display. )

  PUSH DX              ; Preserve registers.
  PUSH BX              ;

output_loop:          ;
    XOR DX, DX        ; Zero DX for correct division.
    DIV ten          ; Extract the last decimal digit of AX:
                      ;  AX gets the integer part of (AX/10),
                      ;  DX ( actually DL ) gets the residual.
    MOV BX, AX        ; Preserve the integer part in BX.
    ADD DL, '0'      ; Actually DL holds the last digit; convert it to
                      ; ASCII code of the corresponding character...
    MOV AH, 2        ; 
    INT 21h          ;  ... and display it on the screen.
                      ;
    MOV AX, BX        ; Restore the integer part for the next iteration.
    CMP AX, 0        ; If there are still digits in the number...
    JNE output_loop  ;  ... then go to the next iteration.

  POP BX              ; Restore registers...
  POP DX              ;
  RET                  ;      ... and return.
display_number ENDP


;--------------------------------------------------------------------------
; 5. 'report' - for each bit in AX,BX,CX,DX display the percent of clock
;    ticks in which it was 1.
;--------------------------------------------------------------------------

report PROC
  PUSH AX                    ;
  PUSH BX
  PUSH CX                    ;
  PUSH DX                    ;
  PUSH SI                    ; Preserve registers.
  PUSH DS                    ;

  MOV SI, 0                  ; SI will be an index in count_array,
                              ; starts from zero.

  MOV DX, SEG report_string  ;
  MOV DS, DX                  ; Display 'report' string for the user.
  MOV DX, OFFSET report_string;
  MOV AH, 9                  ;
  INT 21h                    ;

  MOV DX, SEG ax_string      ;
  MOV DS, DX                  ; Display 'AX:' string for the user.
  MOV DX, OFFSET ax_string    ;
  MOV AH, 9                  ;
  INT 21h                    ;

  MOV CX, 16                  ; There are 16 bits in AX.
display_ax_loop:            ;
    MOV DL, ' '              ; Space to separate between numbers.
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, cs:count_array[SI]  ; Get the value n of a counter.
    MUL hundred    ; DX:AX<-100*n        : Convert to percents:
    DIV cs:max_ticks  ; AX<-100*n/max_ticks : (percent among all ticks) =
                              ;            100*(counter value)/(num.ticks).
    CALL display_number      ; Display on the screen.
    ADD SI, 2                ; Move to the next counter ( 2 bytes ).
    LOOP display_ax_loop      ;

  jmp Skip ; Chingachguk

  MOV DX, SEG bx_string      ; The same things for BX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET bx_string    ;
  MOV AX, 9                  ;
  INT 21h                    ;
  MOV CX, 16                  ;
display_bx_loop:            ;
    MOV DL, ' '              ;
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, count_array[SI]  ; ( In the previous loop SI arrived exactly
    MUL hundred              ;  to the counters that hold BX statistics. )
    DIV cs:n_ticks              ;
    CALL display_number      ;
    ADD SI, 2                ;
    LOOP display_bx_loop      ;

  MOV DX, SEG cx_string      ; The same things for CX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET cx_string    ;
  MOV AX, 9                  ;
  INT 21h                    ;
  MOV CX, 16                  ;
display_cx_loop:            ;
    MOV DL, ' '              ;
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, count_array[SI]  ;
    MUL hundred              ;
    DIV cs:n_ticks              ;
    CALL display_number      ;
    ADD SI, 2                ;
    LOOP display_cx_loop      ;

  MOV DX, SEG dx_string      ; The same things for DX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET dx_string    ;
  MOV AX, 9                  ;
  INT 21h                    ;
  MOV CX, 16                  ;
display_dx_loop:            ;
    MOV DL, ' '              ;
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, count_array[SI]  ;
    MUL hundred              ;
    DIV cs:n_ticks              ;
    CALL display_number      ;
    ADD SI, 2                ;
    LOOP display_dx_loop      ;

Skip:

  POP DS                      ;
  POP SI
  POP DX                      ; Restore registers...
  POP CX                      ;
  POP BX                      ;
  POP AX                      ;
  RET                        ;    ... and return.
report ENDP


;--------------------------------------------------------------------------
; 6. 'input_time_interval' - the user inputs a positive integer number of
;    seconds in the requested time interval, the number returns in AX;
;    if it was not in the range 1...3600 seconds, the routine sets it to 60.
;--------------------------------------------------------------------------

input_time_interval PROC  ; ( Returned value: AX - number of seconds. )

  PUSH BX                      ;
  PUSH CX                      ; Preserve registers.
  PUSH DX                      ;
  PUSH DS                     
                              ; The number will be built digit-by-digit
  XOR AX, AX                  ; in AX; starts from zero.
                               
  input_loop:                  ; Each iteration adds a digit at the end
                              ; of AX ( e.g. AX=123,input '4' -> AX=1234 )
      MOV DX, AX              ; Preserve the previous value (123) in DX.
      MOV AH, 1                ; Get the next datum from the keyboard
      INT 21h          ; AL<-'4'  ( it arrives to AL ).
      CMP AL, 13              ; If it is ENTER...
      JE end_input            ;      ... then the input ends.
                              ; Otherwise: convert the ASCII code
      ADD AL, '0'      ; AL<-4            of a digit to the digit itself
      MOV BL, AL              ; and copy it to BL...
      MOV BH, 0                ;      ... and to BX. ( BX=4 )
      MOV AX, DX              ; Restore the previous value in AX (AX<-123).
      MUL ten          ; AX<-1230
      JO input_error          ; If overflow ( number too big ) then error.
      ADD AX, BX      ; AX<-1234
      JO input_error          ; If overflow ( number too big ) then error.
    JMP input_loop            ; Otherwise go to the next iteration.

end_input:                    ; When the input ends:
    CMP AX, 3600              ;  a) If it is too big...
    JG input_error            ;      ... then it is an error.
    CMP AX, 0                  ;  b) If the number is really positive...
    JG return_number          ;    ... then return it.

input_error:                  ; If there was any error:
    MOV DX, SEG error_string  ;
    MOV DS, DX                ;
    MOV DX, OFFSET error_string;
    MOV AH, 9                  ;  a) Display the error message.
    INT 21h                    ;
    MOV AX, 60                ;  b) Set the number to be 60 seconds.

return_number:                ; In any case:
  POP DS                      ;
  POP DX                      ; Restore registers...
  POP CX                      ;
  POP BX                      ;
  RET                          ;  ... and return ( return AX ).
input_time_interval ENDP


;--------------------------------------------------------------------------
; 7. The main program - input time interval from the user, set new ISR 8
;    that will count how many times each bit in AX,BX,CX,DX was 1 at
;    clock ticks during this interval, then display the results.
;--------------------------------------------------------------------------

main:
  MOV AX, @DATA
  MOV DS, AX
 
  MOV AX, 0                  ;
  MOV ES, AX                  ; Point to segment 0.
  MOV AX, ES:[8*4]            ;
  MOV WORD PTR cs:oldint8_offset,ax; Save old ISR 8 address. ; Chingachguk
  MOV AX, ES:[8*4+2]          ;
  MOV WORD PTR cs:oldint8_seg,ax ; ; Chingachguk
 
  MOV DX, OFFSET prompt_string;
  MOV AH, 9                  ; Prompt the user to enter the time interval.
  INT 21h                    ;
  CALL input_time_interval    ; Input the time interval from the user
                              ;            ( the value t returned in AX ).
  MUL const182      ; DX:AX <- t*182  :
  DIV ten          ; AX <- t*18.2    : Convert seconds to ticks.

  mov ax,18*2

  MOV cs:max_ticks, AX          ; max_ticks gets the time interval in ticks.

  MOV AX, OFFSET newint8      ;
  MOV BX, SEG newint8        ; Compute new ISR 8 address.
  CLI                        ;
  MOV ES:[8*4], AX            ; Write the new addresses to the IV.
  MOV ES:[8*4+2], BX          ;
  STI                        ; The counting starts here.
 
waiting_loop:                ; The main program begins to wait...
; Chingachguk    MOV AX, flag              ;
; Chingachguk    CMP AX, 0                ;    ... until flag=0  ( newint8 will signal
    cmp cs:flag,0
    JNE waiting_loop          ;                the end by setting flag<-0 )

; Restore !!! vector 08h
  MOV AX, 0                  ;
  MOV ES, AX                  ; Point to segment 0.
  MOV AX,WORD PTR cs:oldint8_offset ; Save old ISR 8 address. ; Chingachguk
  MOV ES:[8*4],AX            ;
  MOV AX,WORD PTR cs:oldint8_seg ; ; Chingachguk
  MOV ES:[8*4+2],AX        ;

  CALL report                ; Display the results when the counting stops.


  MOV DX, OFFSET finish_string;
  MOV AH, 9                  ; Display the message 'Finished'.
  INT 21h                    ;

  MOV AH, 4Ch                ; Terminate the program.
  INT 21h                    ; ( IV was restored in newint8. )
                             
END main




--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Unregistered
Дата 7.1.2004, 16:29 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Дорогой, Chingachguk огромное спасибо... но у меня никак не получатся исправить эту функцию ввода - хотя прога компилируется уже и ето COOL, если можешь то спаси страждущую душу....

  Вверх
Chingachguk
Дата 8.1.2004, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: нет
Всего: 18



Держи. Что там выводит final report - я не смотрел. Но что-то выводит ;)

Цитата

.MODEL LARGE

.STACK 1000

.DATA

; Screen messages to display to the user.

prompt_string  DB 'Please enter the time interval in seconds,',13,10
                DB 'no more than 3600 seconds ( an hour ): $'

error_string    DB 13,10,10,'Input error! The interval'
                DB ' set to 60 seconds ( a minute ).',13,10,'$'

report_string  DB 13,10,'Final report:',13,10,'$'

ax_string      DB 13,10,'AX:$'
bx_string      DB 13,10,'BX:$'
cx_string      DB 13,10,'CX:$'
dx_string      DB 13,10,'DX:$'

finish_string  DB 13,10,10,'Finished.',13,10,'$'

; Three constants for technical needs.
hundred        DW 100
ten            DW 10
const182        DW 182

;=============================================================================
;=============================================================================

.CODE

;--------------------------------------------------------------------------
; 1. Declarations of variables to handle interrupt 8 and counting.
;--------------------------------------------------------------------------

                                ; Array of counters initialized by zeroes:
count_array    DW 16 DUP (0)  ; 16 counters for 16 bits of AX ,
                DW 16 DUP (0)  ; 16          for            BX ,
                DW 16 DUP (0)  ; 16          for            CX ,
                DW 16 DUP (0)  ; 16          for            DX .

n_ticks          DW 0          ; Ticks from the beginning, initially zero.
max_ticks      DW (?)        ; Ticks in the requested time interval.

; Chingachguk: change order of declaration

oldint8_offset  DW (?)        ;
oldint8_seg    DW (?)        ; For old ISR 8 address.

flag            DB 1              ; 1 - the counting continues, 0 - finished.

;--------------------------------------------------------------------------
; 2. 'analyse_word' - extract bits from the word given in AX, increment
;    corresponding counters in count_array from count_array[SI] (SI given).
;--------------------------------------------------------------------------

analyse_word PROC FAR        ; ( Arguments: AX - the word to analyse,
                            ;  SI - the index of the first counter. )

  PUSH BX                    ;
  PUSH CX                    ; Preserve registers.
  PUSH DX                   
                            ; BX will be the mask for extracting bits,
  MOV BX, 1                  ; starts from 0000000000000001b.

  MOV CX, 16                ; There are 16 bits in the word.

analyse_loop:              ; Loop over all bits:
                            ;
    MOV DX, AX              ; Copy the word to DX.
    AND DX, BX              ; Extract a bit. DX becomes 0 iff the bit
    CMP DX, 0              ;  matching '1' in the mask is 0; if so
    JE next_bit            ;  then go to the next bit...
                            ;   
    MOV DX, cs:count_array[SI] ;    ... otherwise:
    INC DX                  ;  increment the corresponding counter.
    MOV cs:count_array[SI], DX ;
                            ;
    next_bit:                ; Go to the next bit:
    ADD SI, 2              ; a) Move to the next counter ( 2 bytes ).
    SHL BX, 1              ; b) Move '1' in the mask one position to left.
  LOOP analyse_loop        ; c) Do next iteration.
                             
  POP DX                    ;
  POP CX                    ; Restore registers...
  POP BX                    ;
  RET                        ;  ... and return.
analyse_word ENDP


;--------------------------------------------------------------------------
; 3. 'newint8' routine - at each clock tick analyse bits in AX,BX,CX,DX ,
;    increment n_ticks, signal when the time interval elapses.
;--------------------------------------------------------------------------

newint8 PROC FAR

  PUSH ES                  ;
  PUSH DI                  ;
  PUSH SI                  ;
  PUSH DX                  ; Preserve registers.
  PUSH CX                  ;
  PUSH BX                  ;
  PUSH AX                  ;

; comment by Chingachguk smile.gif
;  MOV AX, oldint8_seg      ;
;  MOV ES, AX                ;
;  MOV BX, oldint8_offset    ; Call old ISR 8.
;  PUSHF                    ;
;  CALL FAR PTR ES:BX        ;
; comment by Chingachguk smile.gif

  ; new: call old int 08h
  pushf
  call dword ptr cs:oldint8_offset
 
; Chingachguk
  MOV AX, cs:n_ticks          ;
  INC AX                    ; Increment n_ticks.
  CMP AX, cs:max_ticks        ; If max_ticks reached...
  JG stop_counting          ;    ... then stop the counting.

continue_counting:        ; otherwise:
    MOV cs:n_ticks, AX        ;  a) Save the incremented value.
    MOV SI, 0              ;  b) The first counter will be No 0.
    POP AX                ;  c) Get the original value of AX for analysis.
    MOV DI, AX            ;  d) Preserve it in DI.
    CALL analyse_word      ;  e) Analyse AX.
                            ;
    POP AX                ;  f) Get the original value of BX for analysis.
    CALL analyse_word      ;  g) Analyse it. ( The loop in 'analyse_word'
                            ;                  advanced SI exactly to the
                            ;                  counters corresponding BX. )
    MOV BX, AX            ;  h) Restore it to BX.
                            ;
    POP AX                ;  i) Get the original value of CX for analysis.
    CALL analyse_word      ;  j) Analyse it.
    MOV CX, AX            ;  k) Restore it to CX.
                            ;
    POP AX                ;  l) Get the original value of DX for analysis.
    CALL analyse_word      ;  m) Analyse it.
    MOV DX, AX            ;  n) Restore it to DX.
                            ;
    MOV AX, DI            ;  o) Restore the original value of AX.
    JMP finish8            ;  p) Finish ISR 8.

stop_counting:            ; When the counting stops:
    XOR AX, AX            ;
    MOV ES, AX            ;
; Chingachguk
    MOV AX, cs:oldint8_offset ;  a) Restore old ISR addresses in the IV.
    MOV BX, cs:oldint8_seg    ;
    CLI                    ;
    MOV ES:[8*4], AX      ;
    MOV ES:[8*4+2], BX    ;
    STI                    ;
    XOR AL, AL            ;  b) Zero the flag to signal the main program
    MOV cs:flag, AL        ;    that the counting finished.
    POP AX                ;
    POP BX                ;  c) Restore AX,BX,CX,DX .
    POP CX                ;
    POP DX                ;
                           
finish8:                  ; The common end:
  POP SI                    ;
  POP DI                    ; restore SI,DI,ES ...
  POP ES                    ;
  IRET                      ;    ... and return.

newint8 ENDP


;--------------------------------------------------------------------------
; 4. 'display_number' - display an integer ( a word ) in AX on the screen.
;--------------------------------------------------------------------------

display_number PROC FAR; ( Argument: AX - the value to display. )

  PUSH DX              ; Preserve registers.
  PUSH BX              ;

output_loop:          ;
    XOR DX, DX        ; Zero DX for correct division.
    DIV ten          ; Extract the last decimal digit of AX:
                      ;  AX gets the integer part of (AX/10),
                      ;  DX ( actually DL ) gets the residual.
    MOV BX, AX        ; Preserve the integer part in BX.
    ADD DL, '0'      ; Actually DL holds the last digit; convert it to
                      ; ASCII code of the corresponding character...
    MOV AH, 2        ; 
    INT 21h          ;  ... and display it on the screen.
                      ;
    MOV AX, BX        ; Restore the integer part for the next iteration.
    CMP AX, 0        ; If there are still digits in the number...
    JNE output_loop  ;  ... then go to the next iteration.

  POP BX              ; Restore registers...
  POP DX              ;
  RET                  ;      ... and return.
display_number ENDP


;--------------------------------------------------------------------------
; 5. 'report' - for each bit in AX,BX,CX,DX display the percent of clock
;    ticks in which it was 1.
;--------------------------------------------------------------------------

report PROC
  PUSH AX                    ;
  PUSH BX
  PUSH CX                    ;
  PUSH DX                    ;
  PUSH SI                    ; Preserve registers.
  PUSH DS                    ;

  MOV SI, 0                  ; SI will be an index in count_array,
                              ; starts from zero.

  MOV DX, SEG report_string  ;
  MOV DS, DX                  ; Display 'report' string for the user.
  MOV DX, OFFSET report_string;
  MOV AH, 9                  ;
  INT 21h                    ;

  MOV DX, SEG ax_string      ;
  MOV DS, DX                  ; Display 'AX:' string for the user.
  MOV DX, OFFSET ax_string    ;
  MOV AH, 9                  ;
  INT 21h                    ;

  MOV CX, 16                  ; There are 16 bits in AX.
display_ax_loop:            ;
    MOV DL, ' '              ; Space to separate between numbers.
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, cs:count_array[SI]  ; Get the value n of a counter.
    MUL hundred    ; DX:AX<-100*n        : Convert to percents:
    DIV cs:max_ticks  ; AX<-100*n/max_ticks : (percent among all ticks) =
                              ;            100*(counter value)/(num.ticks).
    CALL display_number      ; Display on the screen.
    ADD SI, 2                ; Move to the next counter ( 2 bytes ).
    LOOP display_ax_loop      ;

  MOV DX, SEG bx_string      ; The same things for BX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET bx_string    ;
  MOV AH, 9                  ;
  INT 21h                    ;
  MOV CX, 16                  ;
display_bx_loop:            ;
    MOV DL, ' '              ;
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, count_array[SI]  ; ( In the previous loop SI arrived exactly
    MUL hundred              ;  to the counters that hold BX statistics. )
    DIV cs:n_ticks              ;
    CALL display_number      ;
    ADD SI, 2                ;
    LOOP display_bx_loop      ;

  MOV DX, SEG cx_string      ; The same things for CX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET cx_string    ;
  MOV AH, 9                  ;
  INT 21h                    ;
  MOV CX, 16                  ;
display_cx_loop:            ;
    MOV DL, ' '              ;
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, count_array[SI]  ;
    MUL hundred              ;
    DIV cs:n_ticks              ;
    CALL display_number      ;
    ADD SI, 2                ;
    LOOP display_cx_loop      ;

  MOV DX, SEG dx_string      ; The same things for DX statistics.
  MOV DS, DX                  ;
  MOV DX, OFFSET dx_string    ;
  MOV AH, 9                  ;
  INT 21h                    ;
  MOV CX, 16                  ;
display_dx_loop:            ;
    MOV DL, ' '              ;
    MOV AH, 2                ;
    INT 21h                  ;
    MOV AX, count_array[SI]  ;
    MUL hundred              ;
    DIV cs:n_ticks              ;
    CALL display_number      ;
    ADD SI, 2                ;
    LOOP display_dx_loop      ;

  POP DS                      ;
  POP SI
  POP DX                      ; Restore registers...
  POP CX                      ;
  POP BX                      ;
  POP AX                      ;
  RET                        ;    ... and return.
report ENDP


;--------------------------------------------------------------------------
; 6. 'input_time_interval' - the user inputs a positive integer number of
;    seconds in the requested time interval, the number returns in AX;
;    if it was not in the range 1...3600 seconds, the routine sets it to 60.
;--------------------------------------------------------------------------

input_time_interval PROC  ; ( Returned value: AX - number of seconds. )

  PUSH BX                      ;
  PUSH CX                      ; Preserve registers.
  PUSH DX                      ;
  PUSH DS                     
                              ; The number will be built digit-by-digit
  XOR BX, BX                  ; in AX; starts from zero.
                               
  input_loop:                  ; Each iteration adds a digit at the end
                              ; of AX ( e.g. AX=123,input '4' -> AX=1234 )
      MOV DX, BX              ; Preserve the previous value (123) in DX.
      MOV AH, 1                ; Get the next datum from the keyboard
      INT 21h          ; AL<-'4'  ( it arrives to AL ).
      CMP AL, 13              ; If it is ENTER...
      JE end_input            ;      ... then the input ends.
                              ; Otherwise: convert the ASCII code
      ; Chingachguk
      SUB AL, '0'      ; AL<-4 of a digit to the digit itself
      MOV BL, AL              ; and copy it to BL...
      MOV BH, 0                ;      ... and to BX. ( BX=4 )
      MOV AX, DX              ; Restore the previous value in AX (AX<-123).
      MUL ten          ; AX<-1230
      JO input_error          ; If overflow ( number too big ) then error.
      ADD BX, AX      ; BX<-1234
      JO input_error          ; If overflow ( number too big ) then error.
    JMP input_loop            ; Otherwise go to the next iteration.

end_input:                    ; When the input ends:
    CMP BX, 3600              ;  a) If it is too big...
    JG input_error            ;      ... then it is an error.
    CMP BX, 0                  ;  b) If the number is really positive...
    JG return_number          ;    ... then return it.

input_error:                  ; If there was any error:
    MOV DX, SEG error_string  ;
    MOV DS, DX                ;
    MOV DX, OFFSET error_string;
    MOV AH, 9                  ;  a) Display the error message.
    INT 21h                    ;
    MOV BX, 60                ;  b) Set the number to be 60 seconds.

return_number:                ; In any case:
  mov ax,bx
  POP DS                      ;
  POP DX                      ; Restore registers...
  POP CX                      ;
  POP BX                      ;
  RET                          ;  ... and return ( return AX ).
input_time_interval ENDP


;--------------------------------------------------------------------------
; 7. The main program - input time interval from the user, set new ISR 8
;    that will count how many times each bit in AX,BX,CX,DX was 1 at
;    clock ticks during this interval, then display the results.
;--------------------------------------------------------------------------

main:
  MOV AX, @DATA
  MOV DS, AX
 
  MOV AX, 0                  ;
  MOV ES, AX                  ; Point to segment 0.
  MOV AX, ES:[8*4]            ;
  MOV WORD PTR cs:oldint8_offset,ax; Save old ISR 8 address. ; Chingachguk
  MOV AX, ES:[8*4+2]          ;
  MOV WORD PTR cs:oldint8_seg,ax ; ; Chingachguk
 
  MOV DX, OFFSET prompt_string;
  MOV AH, 9                  ; Prompt the user to enter the time interval.
  INT 21h                    ;
  CALL input_time_interval    ; Input the time interval from the user
                              ;            ( the value t returned in AX ).
  MUL const182      ; DX:AX <- t*182  :
  DIV ten          ; AX <- t*18.2    : Convert seconds to ticks.

;;  mov ax,18*2

  MOV cs:max_ticks, AX          ; max_ticks gets the time interval in ticks.

  MOV AX, OFFSET newint8      ;
  MOV BX, SEG newint8        ; Compute new ISR 8 address.
  CLI                        ;
  MOV ES:[8*4], AX            ; Write the new addresses to the IV.
  MOV ES:[8*4+2], BX          ;
  STI                        ; The counting starts here.
 
waiting_loop:                ; The main program begins to wait...
; Chingachguk    MOV AX, flag              ;
; Chingachguk    CMP AX, 0                ;    ... until flag=0  ( newint8 will signal
    cmp cs:flag,0
    JNE waiting_loop          ;                the end by setting flag<-0 )

; Restore !!! vector 08h
  MOV AX, 0                  ;
  MOV ES, AX                  ; Point to segment 0.
  MOV AX,WORD PTR cs:oldint8_offset ; Save old ISR 8 address. ; Chingachguk
  MOV ES:[8*4],AX            ;
  MOV AX,WORD PTR cs:oldint8_seg ; ; Chingachguk
  MOV ES:[8*4+2],AX        ;

  CALL report                ; Display the results when the counting stops.


  MOV DX, OFFSET finish_string;
  MOV AH, 9                  ; Display the message 'Finished'.
  INT 21h                    ;

  MOV AH, 4Ch                ; Terminate the program.
  INT 21h                    ; ( IV was restored in newint8. )
                             
END main



--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Yarikon
Дата 8.1.2004, 12:26 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Дорогой, Chingachguk - нет слов одни только слюни Ж-)
Радоти нет придела... огромное спасибо...

  Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Asm: Общие вопросы"
MAKCim
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой КОД.
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, MAKCim.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Asm: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1093 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.