2014-11-14 2 views
0

Я пишу функцию задержки в сборке 8086. Для этого я использую системное время. Сначала я перезапускаю время, а затем зацикливаю до тех пор, пока системное время не станет равным или больше времени, которое я хотел ожидать.Сборка 8086: странное поведение системного времени

Это не должно быть очень сложно. Так что это моя процедура задержки:

delay_using_time PROC NEAR 
push bp  
mov bp, sp 

push ax 
push bx 
push cx 
push dx 

; Set system time (CH = Hour, CL = minute, DH = second, DL = 1/100 sec) 
mov ah, 2Dh 
xor cx, cx ; Now CH = 0 = CL 
xor dx, dx ; DX = 0 = DH = DL 
int 21h 

; We check that the reset did not failed 
CMP al, 0 ; Als al = 255 dan is het setten van de system time mislukt 
JNE exit_delay 

mov bl, [bp+4][0] ; We put the argument in BL --> wait time 

; Debug --> Prints always 0 (so reset was succesfull) 
mov dl, dh 
xor dh, dh 
push dx 
call tprint 

; Loop untill DL = wait time, but the problem is DL is immediately bigger 
compareTime: 
mov ah, 2Ch 
int 21h  ; #sec in DH, #1/100 sec in DL 

; For debug --> I print the number of seconds passed since we reset the time 
mov dl, dh 
xor dh, dh 
push dx 
call tprint 

; If #seconds < wait time (argument) --> loop again until #seconds >= wait time 
CMP dl, bl  

JL compareTime 
JMP exit_delay 

exit_delay: 
pop dx 
pop cx 
pop bx 
pop ax 

mov sp, bp 
pop bp 
ret 2 
delay_using_time ENDP 

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

Сначала я показываю секунды после сброса системного времени. Он отображает 0, поэтому системное время было сброшено правильно. После этого в цикле я показываю количество секунд, прошедших с момента сброса системного времени. Я бы ожидал, что что-то вроде этого 1,1, ..., 1, 2, 2, ..., 2, 3 будет отображаться, когда я передам аргумент 3 (так что я хочу отложить на 3 секунды). (каждый номер отображается много раз, потому что он циклический, и он повторяется много раз в секунду).

Но Когда я проверяю свою процедуру, я вижу цикл выполняется только один раз, когда я вызываю задержку! Таким образом, он отображает непосредственно, например, «54» вместо 1, 2, 3, ..., 54 (что можно было бы ожидать).

Может кто-нибудь сказать мне, почему он так себя ведет? Я действительно не понимаю, я сначала сбросил системное время и отобразил его, чтобы убедиться, что он был сброшен, а затем в цикле я показываю количество секунд. Таким образом, число секунд скачка сразу с 0 (когда я его сбросил), например, 54.

Спасибо за помощь!

+0

Почему вы устанавливаете время с ah = 2d, во-первых? Также я не уверен, что любой вызов gettime уничтожает любые регистры. Более того, вы уничтожаете dl с mov dl, dh. – bestsss

+0

@bestsss Я впервые установил время до полуночи (час, минуты, секунды и сотни до нуля), потому что я передаю в качестве аргумента моей функции время, которое ему приходится задерживать/спать. Поэтому, как только я сброшу время до полуночи, после этого все, что мне нужно сделать, это проверить время и сравнить секунды (время, прошедшее с момента его сброса) с аргументом, переданным процедуре. Если время прошло, то аргумент I снова зациклился. Так что я зацикливаюсь, пока не пройдет время> = аргумент. И дайте время поставить свой результат в регистры CX и DX: CH = час CL = минут DH = второй DL = 1/100 секунд.Set time info: http://bit.ly/1Bp9gTu – HyperZ

+0

@bestsss Я уничтожаю dl с mov dl, dh, потому что хочу передать количество секунд (dh) в процедуру, которая будет отображать аргумент (это число, переданное через стек). Поэтому, если я нажму DX на стек, отображаемое число будет неправильным, потому что DX = (DH DL). Итак, чтобы правильно отобразить количество секунд (dh), я копирую DH в DL. Затем очистите DH (xor dh, dh), чтобы при отображении содержимого DX он фактически отобразил DL (поскольку DH является нулевым и, следовательно, не изменит значение DL). Извините за двойной комментарий, но он должен был долго вписываться в один комментарий. – HyperZ

ответ

0

Я пробовал свой код прошлой ночью, и он выполнялся правильно. Я получил тысячи нулей, те, и двое, и одну тройку.
Ваша программа имеет очевидный способ запустить всего один раз, если значение выхода функции 2Dh было чем-то иным, чем 0. Под реальными значениями выхода DOS должно быть только 0 или 255. Вы пытались сравнить с 255 и прыгать, если они равны? Кроме того, вы можете различать нормальный выход и выход из-за неправильного сброса времени в качестве средства отладки. Может быть, звучит сигнал?

Этот комментарий не совсем верно

; Debug --> Prints always 0 (so reset was succesfull) 

Вы печатаете оригинал 0, что вы положили в DH зарегистрироваться!
Также

JMP exit_delay 

и

mov sp, bp 

довольно лишними.

+0

Действительно, когда я использую секунды, он отлично работает. Но когда я пытаюсь отложить количество 1/100 секунд, например 5 сотен секунд, это ведет себя странно. Таким образом, все, что я изменил, я напечатал значение dl вместо dh (так отображается 1/100 секунды). И я также сравниваю dl с bl, а не dh с bl (сравните секунды). Поэтому мы ожидаем, что так же, как с секунд, отобразится что-то вроде «000..0111..122..233..344..455..5», если мы пройдем в качестве аргумента 5 (чтобы подождать 5 сотен секунд) , Но число, отображаемое сразу, равно 56. На 5/100 сек ниже предел точности таймера? – HyperZ

+0

Значение, которое MS-DOS возвращает за сотые секунды, основано на тикете таймера BIOS, который работает со скоростью 18,2 тика в секунду. Таким образом, разрешение составляет около 55 мс. Я выполнил модифицированную версию вашего кода и получил эти значения в DL в течение 1 секунды (каждый номер появлялся много раз подряд). ** 0,5,10,16,21,27,32,38,43,49,54,60,65,71,76,82,87,93,98,4 ** Увеличение на 5 или 6 соответствует до 100/18.2. Короче говоря, MS-DOS пытается представить иллюзию очень точного времени, но аппаратное обеспечение не позволяет. –

Смежные вопросы