Форум программистов, компьютерный форум, киберфорум
Наши страницы
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/6: Рейтинг темы: голосов - 6, средняя оценка - 4.50
Goodwin98
2525 / 821 / 10
Регистрация: 31.05.2009
Сообщений: 1,672
1

Графический туннель. Как работает код?

30.06.2009, 03:16. Просмотров 1018. Ответов 10
Метки нет (Все метки)

А сможет ли кто-нибудь обьяснить мне как работает этот код?(фасм)
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
org 100h
use16
 
    mov al, 0x13
    cmc
    inc dx
    int 0x10
    push word 0xa000
    pop es
 
pix:
    mul bx 
    inc ax
    add ax, di
    adc [si], bx   ; изначально 20CDh
    div word [si+12]
clp:
    fmul dword [si]
    fiadd word [si]
    fistp word [bx]
    sub ax, 83h ; устанавливает центр 
    xchg ax, [bx]
    xor cx, ax
    fild word [bx]
    fmul st,st
    xor bx, bp
    xchg ax, dx
    fxch st1
    jnz clp
 
    faddp st1, st0
    fsqrt
    fdivr dword [si]
    fild word [bx]
    fild word [bp]
    fpatan
 
    setalc
    xchg ax, cx
    or al, 0x87
    stosb
    jmp short pix
В частности мне очень интересно, где изменяется bx и/или bp?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.06.2009, 03:16
Ответы с готовыми решениями:

Не работает IPSec Туннель между 2-мя роутерами
Помогите пожалуйста. Есть 2 микротика 951-х. Настроил между ними Туннель, как показано на...

Не работает gre туннель из локальной сети на Cisco 2921/K9
Добрый день! Есть маршрутизатор Cisco 2921/K9. На него заведено два провайдера, и есть две...

Код написан в Dev C. Не работает в Visual. Как нужно переделать код?
Здравствуйте. Столкнулась с такой проблемой: код был написан в Dev C, но в Visual он выдаёт...

Код выполняемый из студии с пометкой debag, работает не так как уже компилированный код
Здравствуйте, столкнулся с такой проблемой. Код выполняемый из студии с пометкой debag, работает не...

Как поднять VPN туннель между двумя роутерами?
Доброе время суток! Пожалуйста, не отсылайте меня в гугл или поиск - я уже три дня подряд весь...

10
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
10.07.2014, 11:07 2
Код используется как данные.

si при запуске равен 256, то есть указывает на точку входа, соответственно si+12 указывает на инструкцию "inc ax". Инструкции "cmc" и "inc dx" вначале - это данные и судя по всему никакой полезной работы не выполняют.

bx при запуске равен 0, bp - 2332. Внутренний цикл выполняется 2 раза: на первой итерации bx=0, на второй - 2332. По окончании цикла bx обнуляется. Таким образом "mul bx" вначале цикла используется для обнуления регистров ax и dx.

Если убрать магию и развернуть внутренний цикл - получится это
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
org 100h
use16
    mov al, 0x13
    int 0x10
    push word 0xa000
    pop es
 
    @@:mov    ax,1
       xor    dx,dx
       add    ax, di
       adc    word[_si],0
       div    word [divider]
 
       faddp  st1, st0
       fsqrt
       fdivr  dword [_si]
       fild   [x]
       fild   [y]
       fpatan
 
       fmul   dword [_si]
       fiadd  [_si]
       fistp  [x]
       sub    ax,83h
       xchg   ax,[x]
       fild   [x]
       fmul   st,st
       fxch   st1
       fmul   dword [_si]
       fiadd  [_si]
       fistp  [y]
       sub    dx,83h
       xchg   dx,[y]
       xor    ax,dx
       fild   [y]
       fmul   st,st
       fxch   st1
 
       or     al,87h
       stosb
   jmp @b
 
_si     dw 5040,17141
divider dw 0140h
x       dw 8397
y       rw 1
Мне кажется код можно соптимизировать - есть лишние обращения к переменным x и y.

Добавлено через 5 минут
Вот немного комментариев к оригинальному коду
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
org 100h
use16
    mov al, 0x13       ;Сюда указывает si
    cmc                ;Эти две инструкции - данные
    inc dx             ;Используются при обращении к dword[si]
    int 0x10
    push word 0xa000
    pop es
 
pix:
    mul bx             ;обнуляем ax и dx
    inc ax
    add ax, di
    adc [si], bx
    div word [si+12]
clp:
    fmul dword [si]
    fiadd word [si]
    fistp word [bx]
    sub ax, 83h        ; устанавливает центр 
    xchg ax, [bx]
    xor cx, ax
    fild word [bx]
    fmul st,st
    xor bx, bp         ;На первой итерации bx=0, на второй bx=bp, на третьей bx=0
    xchg ax, dx
    fxch st1
    jnz clp            ;Цикл выполнится 2 раза
 
    faddp st1, st0
    fsqrt
    fdivr dword [si]
    fild word [bx]
    fild word [bp]
    fpatan
 
    setalc             ;Обнуляем ax
    xchg ax, cx
    or al, 0x87
    stosb              ;Вывод пикселя на экран
    jmp short pix
0
Mikl___
Автор FAQ
13486 / 6417 / 635
Регистрация: 11.11.2010
Сообщений: 11,588
10.07.2014, 11:40 3
murderer,
FAQ для раздела Assembler, MASM, TASM http://www.cyberforum.ru/cgi-bin/latex.cgi?\rightarrow "Графика DOS. Двигаемся в туннеле"
  • Tunnel - 256 bytes
  • Графика DOS. Еще один туннель
1
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
10.07.2014, 12:52 4
Посмотрел - используются те же формулы, что и здесь, но тут всё это утрамбовано в 64 байта. Когда первый раз наткнулся на эту тему около года назад вообще ничего не понял. Теперь некоторые хитрости прояснились. Не уверен оправдано ли здесь использование внутреннего цикла с "xor bx,bp" - возможно получится написать проще и уложиться в 64 байта.

Добавлено через 55 минут
Я понял сакральный смысл переменной в [si] - это float, отвечающий за угол поворота тоннеля.

Вот здесь происходит приращение угла вначале каждого кадра (при переполнении di)
Assembler
1
adc [si], bx
0
10.07.2014, 12:52
Mikl___
Автор FAQ
13486 / 6417 / 635
Регистрация: 11.11.2010
Сообщений: 11,588
10.07.2014, 13:05 5
Цитата Сообщение от murderer Посмотреть сообщение
возможно получится написать проще и уложиться в 64 байта
Только предусмотри выход из программы по "Esc" и ты не ответил по "Win64"
0
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
10.07.2014, 17:33 6
Лучший ответ Сообщение было отмечено Taatshi как решение

Решение

В основе тоннеля лежат две функции:
1) Обратная зависимость от расстояния до центра - это поперечные линии. Спросите почему обратная? Отвечаю - для перспективной проекции.
2) Угол между вектором (x,y) и любой неподвижной прямой на плоскости - это продольные линии.

Иными словами прямоугольные координаты переводятся в полярные.

ФормулаНазвание: dist.png
Просмотров: 87

Размер: 714 байтНазвание: atan.png
Просмотров: 87

Размер: 864 байт
Результат
Графический туннель. Как работает код?
Графический туннель. Как работает код?

Комбинируя результаты этих двух функций можно получить более сложные изображения

ORANDXORADDMUL
Графический туннель. Как работает код?
Графический туннель. Как работает код?
Графический туннель. Как работает код?
Графический туннель. Как работает код?
Графический туннель. Как работает код?

Чтобы вращать изображение достаточно прибавить к результату расчёта номер текущего кадра. Но старые мастера делали по-другому - вместо того, чтобы изменять всё изображение достаточно изменить палитру. Об этой технике можно прочитать здесь.
0
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
10.07.2014, 17:51 7
и ты не ответил по "Win64"
Я не вижу смысла в переводе Iczelion`а под x64 - разница минимальна.

Для того, чтобы начать программировать под x64 нужно научиться программировать под x86 и прочитать это.
0
Mikl___
Автор FAQ
13486 / 6417 / 635
Регистрация: 11.11.2010
Сообщений: 11,588
11.07.2014, 04:24 8
murderer,
перенес твою статью и исходник из поста Goodwin98 в F.A.Q.
0
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
11.07.2014, 12:00 9
Я собираюсь продолжить. Будет рассмотрен другой подход - вместо преобразования Декартовых координат в полярные можно преобразовывать полярные координаты в Декартовы (формулы проще).

Добавлено через 3 часа 11 минут
Тоннель для слоупоков. VESA используется не по стандарту, но в DOSBox работает... очччччень мееееедлеееенннооооо
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
org 100h
mov ax,4F02h
mov bx,103h
int 10h
 
mov dword[bp+2],1024.0
 
@@:inc     dword[bp+1]
   shr     word[bp],8
 
   fild    word[bp]
   fld     dword[bp+2]
   fsincos
   fmul    st0,st2
   fistp   dword[bp+8]
   fmul    st0,st1
   fistp   dword[bp+12]
   fidivr  [c1000]
   fistp   word[bp+16]
 
   mov     ax,[bp+16]
   mov     cx,[bp+3]
   sub     ax,[bp+4]
   add     cx,[bp+4]
   xor     ax,cx
 
   shl     word[bp],8
 
   mov     cx,[bp+8]
   mov     dx,[bp+12]
   add     cx,400
   add     dx,300
 
   mov ah,12
   int 10h
jmp @b
 
c1000         dw 3000
0
Вложения
Тип файла: 7z 1.7z (203 байт, 4 просмотров)
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
11.07.2014, 20:58 10
Код из предыдущего поста конечно никуда не годится, но я хочу обратить внимание на оригинальный трюк, который я использовал. Идея пришла при изучении кода из первого поста - там одна и та же переменная интерпретируется как два разных значения.

Тот подход, который я использовал требует 3 вложенных циклов:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//angle  - угловая координата
//r      - радиальная координата
//frame  - номер кадра
//ox, oy - координаты центра экрана
repeat
  angle:=0;
  repeat
    r:=0;
    repeat
      Pixels[ox+round(cos(angle)*r),oy+round(sin(angle)*r)]:=(round(c1/r)-frame) xor (round(angle*с2)+frame);
      r:=r+1;
    until
    angle:=angle+step;
  until angle<2*PI;
  frame:=frame+1;
until false;
Однако умелое обращение с циклической арифметикой позволяет упаковать всё это (с некоторыми огрехами) в один цикл. Итак что я сделал:

1) Для начала объединим все три переменные-счётчика следующим образом
Графический туннель. Как работает код?

Теперь если выполнять инкремент переменной r так
Assembler
1
inc dword[r]
Будут циклически увеличиваться угловая координата (в младших 23 битах находится мантисса) и номер кадра.
2) Подбираем значение экспоненты таким образом, чтобы число 65536 (период переполнения слова) приблизительно соответствовало 2*PI. В нашем случае подходящая экспонента у числа 1024, а 2*PI = 8

Не знаю, понятно ли это всё неподготовленному разуму... Вот так приблизительно это выглядит в коде
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
coords:   packed record
          r:        byte;
          angle:    word;
          frame:    byte;
          reserved: byte;
          end;
 
...
 
repeat
  with coords do
  begin
    inc(PCardinal(@r)^);
    Pixels[round(ox+cos(PSingle(@angle)^)*r),round(oy+sin(PSingle(@angle)^)*r)]:=(round(c/r)-frame) xor (pword(PAnsiChar(@angle)+1)^+frame);
  end;
until false;
В данном конкретном случае не получилось получить хоть какой-нибудь выигрыш от этого приёма, но возможно найдётся другая задача где получится применить эту хитрость.

Во вложении исходник на Delphi / basm
как это выглядит
Графический туннель. Как работает код?
1
Вложения
Тип файла: 7z tunel.7z (8.6 Кб, 6 просмотров)
murderer
4293 / 1557 / 156
Регистрация: 06.10.2010
Сообщений: 3,448
13.07.2014, 08:27 11
Демо называется constant evolution от Farbrausch.
0
13.07.2014, 08:27
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.07.2014, 08:27

Как открыть на Mikrotik VPN туннель для подключения по RDP?
Скажите пожалуйста как открыть на Mikrotik VPN туннель для подключение по RDP, наше сервер 1С...

Как создать второй активный туннель через резервный маршрут
Уважаемые гуру, требуется совет. Есть cisco ASA, на ней несколько провайдеров, есть основной...

Не работает графический режим
написал программу, откомпилировал пишет error15: fail not found &lt;graph.tpu&gt; но я ведь включил режим...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru