Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Низкоуровневое программирование для дZенствующих (FAQ) ЯНВАРЬ 2001


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

НИЗКОУРОВНЕВОЕ ПРОГРАММИРОВАНИЕ ДЛЯ ДZЕНСТВУЮЩИХ (FAQ)
АРХИВ MAIL-КОНФЕРЕНЦИИ RTFM_HELPERS ЗА ЯНВАРЬ 2001

Сайт: http://hi-tech.nsys.by/
Информация о конференции: http://hi-tech.nsys.by/forum/
Модератор aka Beltsy: bejenari@beltsy.md
Co-moderator aka Serrgio: serrgio@gorki.unibel.by


                        [В О П Р О С - О Т В Е Т]

=======================================================================

ВОПРОС:   При компиляции программ отладчик выдает код A2034: must be in
          segment block как избавиться от этой ошибки?

BELTSY:   Отладчик программы НЕ КОМПИЛИРУЕТ, этим занимается
          КОМПИЛЯТОР!!! Следовательно, при компиляции ОТЛАДЧИК не может
          НИЧЕГО "выдавать".

-----------------------------------------------------------------------

ВОПРОС:   Из #9 (РАЗБОРКИ С ПРОЦЕДУРАМИ, п.3) цитирую:

          :0100 XOR AL,AL    ;первое окошко рисуем, как и раньше...
          :0102 MOV BH,10
          :0104 MOV CH,05
          :0106 MOV CL,10
          :0108 MOV DH,10
          :010A MOV DL,3E
          :010C MOV AH,06
          :010E INT 10
          :0110 CALL 011E    ;четыре раза вызываем подпрограмму,
                             ;начинающуюся по адресу 011E.

          Вот тут у меня вопрос: как мне узнать этот адрес 011E? Ведь
          когда я пишу программу, я не знаю точного адреса начала
          будущей подпрограммы.

BELTSY:   Когда Вы пишете программу, Вы используете метки (label), а
          ассемблер их уже переводит в эти цифры. Приведенный Вами код
          - написан на МИКРОассемблере, там АДРЕСА меток нужно
          просчитывать самому, что совсем не сложно. Зная, что
          программа начинается со смещения 100h и количество байт
          которые занимает каждая команда, пишем программу и
          подщитываем ;). Изврат, конечно, но зато очень хорошее
          упражнение для мозгов :).

-----------------------------------------------------------------------

ВОПРОС:   Существует ли какой нибудь декомпилятор Виндовых *.hlp
          файлов?

SERRGIO:  Есть такая хорошая среда для разработки разнообразных хелпов
          -
          RoboHELP Office. И в ней среди разнообразных тулсов есть и
          Help-to-Source aka "декомпилятор Виндовых (да и всех прочих)
          *.hlp файлов".

-----------------------------------------------------------------------

ВОПРОС:   Каким образом можно записать BOOT-сектор? Может какое
          прерывание есть под это?

BELTSY:   BOOT сектор это всего-лишь самый первый сектор на диске, т.е.
          самые первые 512 байт. Поэтому писать в него можно темже
          прерыванием, что и в любой другой, т.е. биосовским 13h,
          функция ah=03.

-----------------------------------------------------------------------

ВОПРОС:   ...вот такую наипростейшую программу сассемблировать в
          дебаггере и заставить работать аккуратно не получается:

          text segment 'code'
          assume CS:text, DS:text
          begin: mov  AX,text
                 mov  DS,AX
                 mov  AH,09h
                 mov  DX,offset message
                 int  21h
                 mov  AH,4Ch
                 mov  AL,00h
                 int  21h
          message db  'Привет!$'
          text ends
          end  begin

          Как эта программа выглядит в дебаге при ассемблировании?

BELTSY:   Не знаю зачем Вы заносите в DS значение text, Вы же assume
          написали, этого достаточно, DS и так уже какой надо... Но это
          Ваши проблемы ;)

          А в дебаге ЭТО вот как "выгледеть" должно:

          -a
          1A2A:0100 mov ah,09
          1A2A:0102 mov dx,10D
          1A2A:0105 int 21
          1A2A:0107 mov ah,4C
          1A2A:0109 mov al,00
          1A2A:010B int 21
          1A2A:010D
          -e 10D 'Привет!$'
          -d 100
          [дамп памяти опущен]
          -g
          Привет!
          C:\>_

-----------------------------------------------------------------------

ВОПРОС:   Я читаю сейчас на 5-й раз 4-й выпуск рассылки и так не могу
          понять, почему при выводе дампа и подсчете колличества RAM'а,
          мы меняли значения наоборот, т.е. там было написанно 81 32h,
          а переводить и складывать мы должны были 32 81h, ведь когда
          вы присваиваете регистру AX=27f4h Вы же присваеваете AH=27h,
          а AL=f4h  и в регистре эти значения не меняются местами,
          по-крайней мере у вас там так написанно.

YOSHI:    В памяти данные хранятся: МЛАДШИЙ БАЙТ ПО МЛАДШЕМУ АДРЕСУ.
          Например, мы определили в ассемблере слово: ... dw 1234h.
          Здесь 12h - старший байт, 34h - младший. Следуя принципу
          "младший байт по младшему адресу", выходит, что в памяти это
          слово будет храниться как 34 12 (проверь в отладчике!). Если
          к этому слову обращаться как к "слову", то все буден
          нормально, а если обращаться побайтно, то вот тут уже
          придется менять их местами. А с AX все в порядке: AH -
          старшая часть, AL - младшая. Присваивая AX значение 1234h
          (mov ax,1234h), AH присваивается 12h, AL присваивается 34h.

-----------------------------------------------------------------------

ВОПРОС:   Что делает комманда XOR?

YOSHI:    XOR - побитовая операция логического исключающего ИЛИ над
          двумя операндами, результатом которой является "истина", если
          только один из двух операндов имеет значение "истина". И
          "ложь", если оба операнда имеют значение "ложь" или "истина".
          (Короче, если биты разные, то результат - 1, а если
          одинаковые, то результат - 0).

          Таблица истинности:

          A  B  C
          =======
          0  0  0
          0  1  1
          1  0  1
          1  1  0

          С помощью XOR можно инвертировать биты:

          xor ax,ax  ;очистили ax
          xor al,01h ;инвертировали первый бит, теперь al=0001b
          xor al,01h ;инвертировали первый бит, теперь al=0000b

ZERO-Q    Дополним :)

          11  07  06  04  02  00
          OF  SF  ZF  AF  PF  CF
          0   R   R   ?   R   0

          OF, SF, ZF, AF, PF, CF - такие вот мнемоники флагового
          регистра;

          11, 07, 06, 04, 02, 00 - номера битов оного;

          Значения:

          0 - после выполнения команды флаг равен 0 (сбрасывается);
          R - значение зависит от результата;
          ? - флаг неопределен.

          Схемка такая вот:
          xor приемник,источник
          Результат операции помещается в приемник (или в первый
          операнд).

-----------------------------------------------------------------------

ВОПРОС:   По какому адресу находиться видеопамять в режиме 640x480?

S. YAR:   Если мне не изменяет память, во всех ГРАФИЧЕСКИХ режимах плат
          EGA и VGA (и всех более современных плат в совместимых с VGA
          режимах) видеопамять начинается по адресу 0A000h:0. Только
          нужно знать организацию этой видеопамяти - она (организация)
          разная в разных режимах... Очевидно, в вопросе речь идет о
          режиме VGA, 640x480, 16 цветов... В этом режиме видеопамять
          разбита на 4 цветовые плоскости, в один момент времени в
          адресуется только одна (смена производится записью в
          соответствующий IO-регистр VGA-контроллера). Один
          единовременно адресуемый байт видеопамяти отвечает за 8
          смежных (по горизонтали) точек экрана. Это вкратце...

=======================================================================


                        [О Б С У Ж Д Е Н И Е]

=======================================================================

WARORC    Чем отличается файл типа .com , от файла типа .txt, имхо,
          когда я смотрел в NC, то я никакой разницы в коде не заметил,
          но компьютер-то определяет, что этот надо интерпретировать
          как код для выполнения, так вот в чем различия, разъясните
          мне, плз.?

ZERO-Q    Расширением!! ;-)

          Не компьютер определяет, а проце$$ор, а ему, чесна говоря,
          по-барабану какой "хлам" в него летит. Ах. В том то и
          прелесть низкоуровневого программинга.

          А еще появились вот какие соображения: Создаем в любом
          ДОСовском текстовом редакторе файл со следующим содержимым:

          Alt+049 Alt+0192 Alt+064 Alt+0205 Alt+032.

          Сохраняем его, например как, 1.txt.
          Запускаем уже полюбившийся нам дZебургер, даем команды:

          -n 1.txt
          -l
          -g

          и видим:

          Нормальное завершение работы проги.

          Даем команду:

          -u100

          и видим:

          :0100 xor ax,ax
          :0102 inc ax
          :0103 int 20

          Даем команду:

          -d100

          и видим:

          :0100 31 C0 40 CD 20

          Открываем файл 1.txt в встроенном редакторе NC видим туже
          самую последовательность хексовых цифр.

          Вывод: разница между .com и .txt - в расширении имени.
          Программы можно писать и таким образом.

          Мораль: никогда не пишите так программы.

WARORC    Я пробывал запускать в дебугере текстовик и он работал. НО
          раз МД или другая операционка, определяет, что делать с
          файлом, то следовательно она смотрит на расширение, но она же
          не мы, т.е. она же не думает, ага это тхт мы его не будем
          давать проццу на выполнение, а раз она их различает, то
          следовательно различия должны быть в коде, а раз их нет,
          то как она умудряется их различать? Это не вопрос, мне просто
          интересно.

BELTSY    Короче так. По сути между txt и com никаких различий НЕТ. Шо
          там набор цифр, шо там тоже самое. Более того, был у нас txt,
          а мы его переименовали в com и стал он com-ом! Попробуй
          сделать так, ну и запусти его. Потом нажимай сразу на Reset
          и читай дальше.

          МС-ДОС не смотрит на код, а только на расширение. Если в
          командной строке введешь С:\>aaaa.txt и нажмешь, то она
          ничего не сделает, а как-тока переименовали все пошло
          ........... на Reset жми.

          В коде различий НЕТ!!! для ДОСа тока в расширениях. А вот в
          других операционках, например UNIX, расширений вообще нету.
          Надеюсь с расширениями разобрались.............

YOSHI     Не совсем согласен. MS-DOS, все-таки, смотрит на код при
          определении формата файла. Например, если дос увидит в
          сигнатуре файла (сигнатура - здесь первые два байта файла)
          код 5A 4D, то есть "MZ" или "ZM", то этот файл дос определяет
          как EXE, если что-то другое, то COM. Можете проверить (правда
          для этого нужно правильно указывать заголовок EXE файла
          формата MZ).

          Пример: Файл COMMAND.COM в windows имеет размер 95,192 Кб.
          Как это COM файл имеет размер более 65,536 Кб??? Да просто
          это самый настоящий EXE, который переименован в COM.

          А вот теперь, надеюсь, разобрались.

BELTSY    Согласен, но не со всем. возьми переименуй ехе-ный файл в
          тотже txt. Ну введи его в командной строке. запустит??? а
          фиг запустит!!! Так что в первую очередь дос смотрит на
          расширение, а уж потом на все остальное!!!

-----------------------------------------------------------------------

ZERO-Q    В девятом выпуске, всем нам известной рассылки
          "Низкоуровневое программирование для ДZенствующих", в пункте
          четвертом [4] есть пример программы, где мы с Вами рисуем
          окошки на дисплее. Я не стал лениться и нарисовал тринадцать
          таких окошечек при помощи следующей последовательности
          нуликов и единичек:

          :0100 mov ax,0600      ;65 байт
          :0103 mov bh,70
          :0105 mov cx,0000
          :0108 mov dx,184f
          :010B int 10
          :010D call 0133
          :0110 call 0133
          :0113 call 0133
          :0116 call 0133
          :0119 call 0133
          :011C call 0133
          :011F call 0133
          :0122 call 0133
          :0125 call 0133
          :0128 call 0133
          :012B call 0133
          :012E call 0133
          :0131 int 20
          :0133 sub bh,10
          :0136 add,cx,0101
          :013A sub dx,0101
          :013E int 10
          :0140 ret

          Захотел я было CALL LOOP-ом закрутить, да вот загвоздка, а
          точнее КОНКУРЕНЦИЯ, на CX претендуют сразу и INT 10 и LOOP.
          Но решил я не отчаиваться и закрутить все это еще через
          СТЕК. Думал я долго и кипели мозги (все как по прогнозу
          SERRGIO), и придумал.

          Ура! Кричу я, брызгая слюной на свой дисплей, а тут как
          кирпичом по голове (наверное это и имеет ввиду SERRGIO);

          В СТЕК? В СТЕК?

          Да тут на стек этот тоже своего рода КОНКУРЕНЦИЯ. Когда
          выполняешь CALL он пихает в стек адрес следующей за ним
          команды, для последующего возвращения по этому адресу
          командой RET (будь она неладна).

          Не это не кирпичом по голове, а прямо как-то веслом по плечу.

          Вообщем дZенствовал  долго и на дZенствовал я следующее:

          :0100 mov ax,0600      ;42 байта
          :0103 mov bx,700C
          :0106 mov cx,0000
          :0109 mov dx,184f
          :010C int 10
          :010E push cx
          :010F jmp 0113
          :0111 mov bl,cl
          :0113 pop cx
          :0114 add cx,0101
          :0118 push cx
          :0119 sub dx,0101
          :011D sub bh,10
          :0120 int 10
          :0122 xor cx,cx
          :0124 mov cl,bl
          :0126 loop 0111
          :0128 int 20

          Во как закрутил!
          Вы представляете! И эта штука работает! Да к тому же так как
          хотелось. Хотя хотелось CALL LOOP-ом завернуть.

          Через некоторое время получилось следующее:

          :0100 mov ax,0600     ;38 байт
          :0103 mov bx,7000
          :0106 mov cx,0000
          :0109 mov dx,184F
          :010C int 10
          :010E cmp bl,0C
          :0111 jz 0124         ;кстати я пишу в своем дZебургере je,
          :0113 add cx,0101     ;а он сам переводит на jz. Кто знает
          :0117 sub dx,0101     ;подскажите почему?
          :011B sub bh,10
          :011E inc bl
          :0120 int 10
          :0122 jmp 010E
          :0124 int 20

          А CALL LOOP-ом я так не закрутил. Дался он мне и все тут.
          Может у кого получалось разрешить такую вот заморочку?

DINOZAUR  Я тоже подзенствовал и родил такое:

          segment qwe 'code'
          assume cs:qwe
          org 100h
          beg:
              mov ax,0600h
              mov bh,70h
              mov cx,0000h
              mov dx,184fh
              int 10h
              mov ax,12
          lpb:
              push ax
              call wnd
              pop ax
              dec ax
              jnz lpb
              int 20h
          wnd:
              mov ax,0600h
              sub bh,10h
              add cx,0101h
              sub dx,0101h
              int 10h
              ret
          ends qwe
          end beg

          Скрестил бульдога с носорогом...

2K        В результате ужасающих по своей ничем необоснованной
          жестокости генетических эксперементов родился
          нижеследующий МОНСТР:

          ;loop+call
          segment kk
          assume cs:kk
          org 100h
          begin:
               mov    ax,0600h
               mov    bh,70h
               mov    cx,0000h
               push   cx
               mov    dx,184fh
               int    10h
               mov    cx,12
               push   cx
               pop    cx
          N_wind:
               push   cx
               call   wnd
               pop    cx
               loop   N_wind
               int    20h
          wnd:
               pop    es
               pop    ds
               pop    cx
               sub    bh,10h
               add    cx,0101h
               sub    dx,0101h
               int    10h
               push   cx
               push   ds
               push   es
               ret
          ends kk
          end begin

          Безумное количество инструкций pop и push! надо с этим что-то
          делать. Но результат налицо -- call работает вместе с loop.

WUNICORN  И это занимает 48 байт ;)

          Если поставить себе задачу сделать именно loop+call, то можно
          вот так (38 байт):

          CODESG    segment
          assume    cs:CODESG
          org       100h
          MAIN      proc
            mov     ax,0600h
            mov     bh,70h
            mov     dx,0184fh
            ;mov    si,0h
            xor     si,si
            mov     cx,0dh
           NextWin:
            xchg    si,cx
            call    WINDOW
            xchg    si,cx
            loop    NextWin
            int     20h
          MAIN      endp
          WINDOW    proc
            int     10h
            sub     bh,10h
            add     cx,0101h
            sub     dx,0101h
            ret
          WINDOW    endp
          CODESG    ends
          end       MAIN

          Но вообще-то для данной задачи ИМХО лучше обойтись вообще
          без call и еще чуть-чуть поизвращаться, тогда можно загнать
          все в 33 байта:

          CODESG    segment
          assume    cs:CODESG
          org       100h
          MAIN      proc
            mov     di,0101h
            mov     ax,0600h
            mov     bh,70h
            mov     dx,0184fh
            xor     si,si
            mov     cx,0dh
           NextWin:
            xchg    si,cx
            int     10h
            sub     bh,10h
            add     cx,di
            sub     dx,di
            xchg    si,cx
            loop    NextWin
            int     20h
          MAIN      endp

          А еще меньше можно ? :)

WUNICORN  Утро вечера мудренее оказалось :) Ведь таки можно еще байт
          выиграть :)

          32 байта:

          CODESG    segment
          assume    cs:CODESG
          org       100h
          MAIN      proc
            mov     di,0101h
            mov     ax,0600h
            mov     bh,70h
            mov     dx,0184fh
            xor     si,si
            mov     cx,0dh
           NextWin:
            xchg    si,cx
            int     10h
            sub     bh,10h
            add     cx,di
            sub     dx,di
            xchg    si,cx
            loop    NextWin
            ;int     20h
            ret             ; Так тоже можно из комушника выйти :)
          MAIN      endp
          CODESG    ends
          end       MAIN

ZERO-Q    dinozaur Вы писали:

          d> закрутить call с loop'ом (Zero-Q)
          d> я тоже подзенствовал и родил такое:

          что-то я не как не догоню вот этот участок:

          .....
          dec ax
          jnz 0110
          int 20

          d> Скрестил бульдога с носорогом...

          Кста, скрестить бульдога с носорогом! Тоже надо уметь.
          И объясните "чайнику" плз, в чем разница между MASM and TASM.
          А то целый час ушел на перекачку 3,9Мб MASM с сайта hi-tech,
          а Serrgio глаголит, что нужен TASM.

DINOZAUR  > d> закрутить call с loop'ом (Zero-Q)
          > d> я тоже подзенствовал и родил такое:
          > что-то я не как не догоню вот этот участок:

          > .....
          > dec ax
          > jnz 0110
          > int 20

          segment qwe 'code'
          assume cs:qwe
          org 100h
          beg:
              mov ax,0600h
              mov bh,70h
              mov cx,0000h
              mov dx,184fh
              int 10h
              mov ax,12             ;число повторов
          lpb:                      ;начало цикла
              push ax               ;сохраняем число повторов
              call wnd              ;выводин окно
              pop ax                ;высстанавливаем число повторов
              dec ax                ;уменьщаем на еденицу его
              jnz lpb               ;если не ноль то на начало цикла
              int 20h               ;если ноль в числе повторов,
          wnd:                      ;то конец :-) ну а тут все ясно
              mov ax,0600h
              sub bh,10h
              add cx,0101h
              sub dx,0101h
              int 10h
              ret
          ends qwe
          end beg

          > d> Скрестил бульдога с носорогом...
          > Кста, скрестить бульдога с носорогом!
          > Тоже надо уметь.

          Гы :-))

          > И объясните "чайнику" плз, в чем разница между MASM and
          > TASM. А то целый час ушел на перекачку 3,9Мб MASM с сайта
          > hi-tech, а Serrgio глаголит, что нужен TASM. Если уж выхода
          > нет, то придется и его качать.

          Для начала разницы нет... я юзаю тасм от Борланд Си 3.0

2K        W> Но вообще-то для данной задачи ИМХО лучше обойтись вообще
          W> без call и еще чуть-чуть поизвращаться, тогда можно
          W> загнать все в 33 байта:
          [..]
          W> А еще меньше можно ? :)

          Можно: заменить последний int 20h на ret. некоторое снижение
          быстродействия, но уже 32 байта.

WUNICORN  G> Можно: заменить последний int 20h на ret. некоторое
          G> снижение быстродействия, но уже 32 байта.

          Ну, это я уже с утра пораньше догадалась и в эху кинула :)
          А вот если уйти от loop, то получается вообще 29 байт:

          CODESG    segment
          assume    cs:CODESG
          org       100h
          MAIN      proc
            mov     di,0101h
            mov     ax,0600h
            mov     bh,70h
            mov     dx,0184fh
            xor     cx,cx
            mov     si,0dh
           NextWin:
            int     10h
            sub     bh,10h
            add     cx,di
            sub     dx,di
            dec     si
            jnz     NextWin
            ret
          MAIN      endp
          CODESG    ends
          end       MAIN

2K        В таком варианте увеличивается скорость (причем увеличение
          прямо пропорционально количеству окошек):

          CODESG    segment
          assume    cs:CODESG
          org       100h
          MAIN      proc
            mov     di,0101h
            mov     ax,0600h
            mov     bx,7010h    ;было mov bh,70h
            mov     dx,0184fh
            xor     cx,cx
            mov     si,0dh
           NextWin:
            int     10h
            sub     bh,bl       ;было sub bh,10h
            add     cx,di
            sub     dx,di
            dec     si
            jnz     NextWin
            ret
          MAIN      endp
          CODESG    ends
          end       MAIN

DINOZAUR  > G> Можно: заменить последний int 20h на ret. некоторое
          > G> снижение быстродействия, но уже 32 байта.

          Ну, на такое снижение можно начхать...  в конце-концов
          программа завершается только один раз :-)

          > А вот если уйти от loop, то получается вообще 29 байт:

          Вообще-то тут используется то, что при вызове int 10 у нас
          регистры сохраняются... Но это не всегда верно... Если
          вызывать свою процедуру, то не факт, что она все так и
          оставит после себя. Правда можно ее заставить(сохранять все
          в стеке при входе и восстанавливать при выходе). Но это
          влечет дополнительные расходы (пролог & эпилог в каждой проц
          писать накладно). Поэтому большинство компиляторов с
          языков высокого уровня так не делает...

ZERO-Q    W> А вот если уйти от loop, то получается вообще 29 байт:

          Кста, сабж письма у Вас, как я понял леди :), проходит как
          loop+call, а от loop Вы пытаетесь убежать :(, что-то как-то
          не в тему, ну да ладно. Все варианты хороши.

          Господа :), хочу Вам сообщить, что я искренне доволен
          подобными письмами. Я вот еще подписан на один офлайновый
          форум по железу, так там такие правила:

          1)задал тему, в течении четырех дней отвечаем;
          2)если ответы помогли и вполне устраивают, то посылается в
          группу письмо с сабжем "Вопрос закрыт".
          Что я с удовольствием и делаю (да не разругается модератор),
          хотя правила в группе вообще не проходили и "награды", я
          думаю мне не сулит.

          Коврик для мыши совершил недопустимую операцию и будет
          свернут :).

=======================================================================
(С) HI-TECH group. All rights reserved and reversed. Оригинальная
грамматика авторов сохранена.

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться Рейтингуется SpyLog

В избранное