LINUX.ORG.RU

[asm][x86] Не могу понять условие перехода (jnz)


0

0

Разбирал через ida, возможно криво, но получилось так:

;               S u b r o u t i n e

sub_0_1F2       proc near               ; CODE XREF: seg000:0186▒p seg000:01D3▒p
                push    dx
                mov     dx, 3DAh       

loc_0_1F6:                              ; CODE XREF: sub_0_1F2+Aj
                mov     ah, 9Fh      
                in      al, dx          ; Video status bits:
                                        ; 0: retrace.  1=display is in vert or horiz retrace.
                                        ; 1: 1=light pen is triggered; 0=armed
                                        ; 2: 1=light pen switch is open; 0=closed
                                        ; 3: 1=vertical sync pulse is occurring.

                and     ax, 408h
                jnz     near ptr loc_0_1F6+1
                pop     dx
                retn
sub_0_1F2       endp

Сохраняем регистр dx на стек, потом читаем из порта 3DAh (я так понял, что это сброс состояния для VGA?), потом... А вот что потом? По идее при AND может быть установлен флаг ZF, т.е. пока не получим 0 при делении, то так и будем долбить чтение с порта?

Меня смушает loc_0_1F6+1 - оно точно перейдет на mov (который тут вообще не используется?), или на следующую команду? Или на следующий байт и из остатка mov будет lahf, заливающий флаги в ah?

Сам бинарник - демка с салютом

очевидно банальное ожидание обратного хода луча для отрисовки.

and ax, 408h - проверка на сброс нужных флагов

если в итоге ax == 0 то выходим из цикла

exception13 ★★★★★ ()
Ответ на: комментарий от exception13

очевидно банальное ожидание обратного хода луча для отрисовки.

оно же данные из порта в al пишет, который не использует, а маску к ax применяет?

Опять же, переход:

вывод hiew:
▓ 000000F2: 52                           push        dx
▓ 000000F3: BADA03                       mov         dx,003DA ;"♥┌"
▓ 000000F6: B49F                         mov         ah,09F ;"Я"
▓ 000000F8: EC                           in          al,dx
▓ 000000F9: 250804                       and         ax,00408 ;"♦◘"
▓ 000000FC: 75F9                         jne         0000000F7  ---↑ (J)
▓ 000000FE: 5A                           pop         dx
▓ 000000FF: C3                           retn

Куда именно оно перейдет?

simple_best_world_web_master ()

если мне не изменяет мой склероз, условный переход на near ptr адрес расценивается как задание адреса для регистра ip, короче как переход на определённую команду. В данном случае - на «in al, dx».

Судя по всему, это ожидающий цикл.

alex_custov ★★★★★ ()
Ответ на: комментарий от alex_custov

> В данном случае - на «in al, dx»

Нет. Перейдет оно на команду с кодом 9F (lahf, если мне память не изменяет). Абсолютный адрес будет 0xF7.

Проверяется просто: при выполнении jnz IP устанавливается в адрес *следующей* инструкции (0xFE); 0xF9 (относительное смещение в JNZ, второй байт команды) = -7. 0xFE - 0x07 = 0xF7.

sjinks ★★★ ()

>Или на следующий байт и из остатка mov будет lahf, заливающий флаги в ah?
именно туда и перейдет.
весьма любопытный ход.

xydo ★★ ()
Ответ на: комментарий от xydo

и тогда на следующий итерациях «and ax, 408h» способствует проверке не только значения, прочтенного из порта, но и флага PF с предыдущей итерации. получается чуть ли не цикл с двойным условием.

xydo ★★ ()
Ответ на: комментарий от alex_custov

near ptr - это означает, что в машинном коде будет задано 8-байтное смещение относительно адреса следующей за jnz командой (т.е. ip=ip+смещение). в остальных случаях задается абсолютный адрес, который прямиком загружается в ip (т.е. ip=адрес).

xydo ★★ ()

Получается ожидание окончания выполнения вертикальной синхронизации. Из-за того, что AH=9F, цикл выполнится как минимум два раза: AND AX(=9Fxx), 0408h даст 04xx, соответственно JNZ перейдет на инструкцию LAHF (тот самый 9F). Третий бит в регистре AH будет соответствовать флагу PF. Флаг PF устанавливается в единицу, если после выполнения AND в регистре AL количество установленных бит НЕчетное.

Подводя итог:

1. Проверка на выполнение вертикальной синхронизации.
2. Проверка на выполнение вертикальной синхронизации.
3. Если вертикальная синхронизация выполняется, переход к п. 2
4. Выход.

Как-то так.

sjinks ★★★ ()
Ответ на: комментарий от sjinks

Пардон, ошибка в п.3: «если вертикальная синхронизация выполняется сейчас ИЛИ выполнялась на предыдущей итерации цикла, то переход к п.2»

sjinks ★★★ ()
Ответ на: комментарий от xydo

Вот интересно, господа промышленные ассмблерщики - за такие ходы надо давать премии или увольнять? Или все вместе?

svu ★★★★★ ()
Ответ на: комментарий от svu

Смотря какая цель стоит. Я не специалист по видеоадаптерам, поэтому не знаю, можно ли написать код проще. А вообще решение чертовски красивое :-)

Если исходник хорошо комментирован, то можно и премию дать.

PS: смотрю на такой код, и вспоминаю известный OneHalf.3544.

sjinks ★★★ ()
Ответ на: комментарий от svu

судя по первому сообщению, этот код - демка.
так что премию!!))

xydo ★★ ()
Ответ на: комментарий от svu

а вообще хорошо, что в природе есть такой код.
есть над чем поломать голову, подумать, потренировать свои мозги.

xydo ★★ ()
Ответ на: комментарий от sjinks

Понятное дело, можно проще, не используя код как данные. Но не так коротко будет, чуть тормознее. Вопрос в том, при промышленном асм программировании (никогда не занимался) такое толерантится или нет?

svu ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.