Форум программистов, компьютерный форум, киберфорум
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.76/203: Рейтинг темы: голосов - 203, средняя оценка - 4.76
188 / 120 / 4
Регистрация: 23.01.2010
Сообщений: 1,320

(MASM32 Editor) для новичков

02.09.2010, 12:58. Показов 41781. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Знающие люди помогите изучить асемблер много литературы но не могу понять его. Знаю только дельфи. опишите где в каких секция что пишеться (думаю тема если будет написана подробно то ее смогут читать новички) Очень интересно!!!
---------------------------------------------------------------
Если я правильно понял

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.486 {это тип процессора указываеться там может быть .386 и Т.Д}
.model flat, stdcall {здесь типа модель памяти плоска но она какая еще бывает Renge если не ошибаюсь, а для чего нужен StdCall } 
option casemap :none     {НЕ ЗНАЮ}
include 868.inc        {слово Include говорит о том что подключаем модуль или файл 869.inc }
 
{как подключить модули API}
 
.code {Я так понял директива после которой начинаеться описание кода}
start: {Зачем она??}
 
{Ниже сложим два числа 10+10}
MOV EAX, 10 
MOV EBX, 10
EAX ADD, EBX
 
ret {это вроде как окончание}
 
end start {??}
Не знаю как тема получилась я старался. Дополните код грамотно с коментарием очень поможет многим ... наверно
2
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.09.2010, 12:58
Ответы с готовыми решениями:

Ошибки MASM32 - cannot open file : .\masm32\include\windows.inc
установил MASM32, прописал в патче путь, выдаёт ошибки при компиляции такого рода : Microsoft (R) Macro Assembler Version 6.14.8444 ...

Несмотря на подключение masm32.inc и masm32.lib не подтягиваются функции stdin и stdout
Собственно скрин.

Как сделать деление BCD чисел на асемблере? MASM32 Editor
Как сделать деление BCD чисел на асемблере? MASM32 Editor:cry:

34
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
03.09.2010, 22:27
Студворк — интернет-сервис помощи студентам
Сколько воды)) никогда это не читал. На мой взгляд обучение лучше начинать сразу с написания программы. А когда возникают проблемы лезть в документацию

Добавлено через 1 минуту
тебе советую так же, а когда возникнут вопросы можешь писать сюда.

Добавлено через 8 минут
Цитата Сообщение от Goodwin98 Посмотреть сообщение
Что это все ?
видимо человек делится своими открытиями))
0
188 / 120 / 4
Регистрация: 23.01.2010
Сообщений: 1,320
04.09.2010, 13:25  [ТС]
Есть еще один момент почему необходимо добавлять внутреие (скажем модули а нельзя на примую обратиться к DLL или всеже в чем кроеться смысл)

ActionScript 3
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
include files
;     ~~~~~~~~~~~~~
      include \masm32\include\windows.inc
      include \masm32\include\masm32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\Comctl32.inc
      include \masm32\include\comdlg32.inc
      include \masm32\include\shell32.inc
      include \masm32\include\oleaut32.inc
      include \masm32\include\msvcrt.inc
      include \masm32\include\dialogs.inc
      include \masm32\macros\macros.asm
 
;     libraries
;     ~~~~~~~~~
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\Comctl32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\oleaut32.lib
      includelib \masm32\lib\msvcrt.lib
Допустим если я хочу вызвать какуюта API функцию можо ли это зделать проще допустим типа так:

function имя (параметр1 : type1 ...); external 'Имя файла.dll' name 'NameFunction';
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
04.09.2010, 13:44
можно имполтировать функции напрямую из длл. Многие компиляторы так и поступают, без всяких lib файлов. Статический импорт(через lib) в некоторых случаях удобнее, т.к. исполняемый файл может содержать функции типа __imp_function_name в качестве импорта, а .lib экспортирует эти же имена и содержит переходники, которыми пользоваться намного удобнее
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
04.09.2010, 13:50
В файле windows.inc хранятся описание констант и структур, которые вы можете использовать при работе с апи. В таких как shell32.inc определения функций, которые есть в этой dll. А в lib файлах информация для компоновщика, о том как вызывать эти функции.

Цитата Сообщение от n971030 Посмотреть сообщение
Допустим если я хочу вызвать какуюта API функцию можо ли это зделать проще допустим типа так:
function имя (параметр1 : type1 ...); external 'Имя файла.dll' name 'NameFunction';
В масме - нет, но такое есть в фасме
0
188 / 120 / 4
Регистрация: 23.01.2010
Сообщений: 1,320
04.09.2010, 14:23  [ТС]
Написал вобще такой код в нем видать чета не правильно не компелируеться обьясните новичку где ошибся.
ActionScript 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.386 
.model flat, stdcall 
 
;include \MASM32\include\kernel32.inc
;include \MASM32\include\user32.inc
 
;include \MASM32\lib\kernel32.lib
;include \MASM32\lib\user.lib
 
.const
    Nm = "d:\1.txt"  ;старый файл
    Ne = "d:\2.txt"  ;новый файл
 
; начинаем код
 
 Main: 
    INVOKE  copyFile  nm, ne, 0
 
 ret 
    end main
0
2014 / 1286 / 61
Регистрация: 05.06.2010
Сообщений: 2,213
04.09.2010, 14:31
а какие ошибки пишет? Если не ошибаюсь регистр важен, т.е. CopyFile

Добавлено через 1 минуту
и строки вроде нулем должны заканчиваться - но это уже не к проблеме компиляции
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
04.09.2010, 14:39
1. Зачем закоментированны строки
Assembler
1
2
3
4
5
;include \MASM32\include\kernel32.inc
;include \MASM32\include\user32.inc
 
;include \MASM32\lib\kernel32.lib
;include \MASM32\lib\user.lib
2. NE это зарезервированное слово его нельзя использовать для меток.
3. Переменные так не обьявляются. Нужно так
Assembler
1
OldFile db "d:\1.txt",0  ;старый файл
В конце строки должен быть ноль.
Причем в секции .data, т.к. это занимает память.
4. Отсутствует строка .code
5. Регистр действительно важен.
6. После имени функции должна стоять запятая.
7. В функцию CopyFile передаются аддреса строк, т.е. вся эта строка должна выглядеть примерно так.
Assembler
1
invoke CopyFile,addr  OldFile, addr NewFile, 0
8. Для правильного завершения программы нужно вызывать ExitProcess.
1
188 / 120 / 4
Регистрация: 23.01.2010
Сообщений: 1,320
04.09.2010, 16:23  [ТС]
Цитата Сообщение от Goodwin98 Посмотреть сообщение
1. Зачем закоментированны строки
Assembler
1
2
3
4
5
;include \MASM32\include\kernel32.inc
;include \MASM32\include\user32.inc
 
;include \MASM32\lib\kernel32.lib
;include \MASM32\lib\user.lib
2. NE это зарезервированное слово его нельзя использовать для меток.
3. Переменные так не обьявляются. Нужно так
Assembler
1
OldFile db "d:\1.txt",0  ;старый файл
В конце строки должен быть ноль.
Причем в секции .data, т.к. это занимает память.
4. Отсутствует строка .code
5. Регистр действительно важен.
6. После имени функции должна стоять запятая.
7. В функцию CopyFile передаются аддреса строк, т.е. вся эта строка должна выглядеть примерно так.
Assembler
1
invoke CopyFile,addr  OldFile, addr NewFile, 0
8. Для правильного завершения программы нужно вызывать ExitProcess.
У меня вобщем такой код получился но выдает массу ошибок.
----------------------------------------------------------------
ActionScript 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.386 
.model flat, stdcall 
 
include \MASM32\include\kernel32.inc
include \MASM32\include\user32.inc
 
include \MASM32\lib\kernel32.lib
include \MASM32\lib\user.lib
 
.const
    OldFile = "d:\1.txt", 0  ;старый файл
    NewFile = "d:\2.txt", 0  ;новый файл
 
; начинаем код
 
.code
    start:
 
    invoke  CopyFile, addr  OldFile, addr NewFile , 0
 
 ret 
    end start
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
04.09.2010, 16:38
3. Пункт не исправлен.
Assembler
1
2
include \MASM32\lib\kernel32.lib
include \MASM32\lib\user.lib
lib файлы нужно с помощью includelib подцеплять.
0
188 / 120 / 4
Регистрация: 23.01.2010
Сообщений: 1,320
15.02.2011, 00:21  [ТС]
Предисловие.
До недавнего времени я полагал, что на свете уже не сущестувует людей, которые не только не могут написать компьютерную игру, но и - страшно сказать! - не могут отличить регистр от порта. Мои наивные предположения развеял недавний визит на рязанский радиорынок в ЦПКиО.
- У вас есть какие-нибудь программы для Синклера?- спросил молодой человек, подойдя к столу в центре площадки.
Меня насторожило уже слово "Синклер": может быть, кто-то еще не знает, но компьютер, на котором Вы читаете этот текст, называется ZX Spectrum, от латинского слова, означающего, кажется, "радуга". Я подошел ближе.
- Извините, я местный кодер. Меня зовут Дима Быстров...- начал я смущенно.
Разговорившись, мы обменялись адресами и простились, пообещав навещать друг друга.
Через пару недель мы снова встретились; каждая моя программа явно удивила моего нового знакомого, который, вероятно, не видел свежего софта уже года два. Я скинул ему основных утилит и пожелал в скором времени написать что-нибудь хорошее.
Прошло еще две недели... Он вернул мои диски и принес старый журнал в глянцевой обложке.
Журнал назывался "Домашний компьютер"; это был, по правде говоря, писюшный журнал ("писюшный" - прилагательное от "писи", каковой термин мы, кодеры, используем вместо IBM PC). Рубрика "ПОМОГИТЕ!" наиболее заинтересовала меня. Это рубрика вопросов читателей журнала и ответов на них, данных неким д-ром Хелпом. Когда я натолкнулся на ЭТИ вопросы, я не смог удержаться от смеха:

"Я внимательно посмотрел на свой компьютер сзади и обнаружил там несколько интересных разъемов. Интересно, что это за разъемы и можно ли их как-то использовать? Мышь и принтер у меня уже подключены. Что можно еще подключить?"
"Очень я люблю играть в игры, но играю всегда один. Друзья мне рассказали, что во многие компьютерные игры можно играть двум игрокам одновременно на разных компьютерах. При этом будто бы можно сражаться на разных сторонах. Как это бывает?Мне никогда не приходилось в такие игры играть."

Следующий вопрос я специально отмечаю. Теперь Вы поймете, к чему я вообще повел эту беседу. Готовьтесь...

"Я недавно купил компьютер. Но пользоваться им я боюсь. Не потому, что я боюсь техники. Просто я не знаю, что надо делать, чтобы избежать поломок? Компьютерная техника довольно сложная, непонятная и совсем не похожа на другую технику. Я больше всего опасаюсь чего-нибудь поломать или испортить."

Далее следует описание того, как компьтер следует пылесосить и протирать тряпочкой. Но самого главного авторы журнала не смогли понять: читатель ПОЛАГАЕТ, ЧТО АППАРАТНУЮ ЧАСТЬ КОМПЬЮТЕРА МОЖНО ИСПОРТИТЬ, НАЖАВ НЕ НА ТУ КНОПКУ!
Развеять подобные мифы и помочь чудаковатым читателям компьютерных журналов почувствовать себя хозяевами своего компьютера и должна эта страничка.

Глава 1
о том, как побороть страх и написать простейшую программу на ассемблере

Во-первых, введу несколько основных понятий, используемых нами и применения которых Вам в будущем не избежать.
КОДЕР - человек, который пишет (делает) программы в машинных кодах.
МАШИННЫЕ КОДЫ - указания процессору Z80 в компьютере, сводящиеся к простейшим вычислительным операциям. Программы в машинных кодах ВСЕГДА быстрее написанных на какихлибо других языках(Бейсик, Паскаль, Си, ...).
АССЕМБЛЕР (АСМ) - метод записи М. К. на бумаге(экране, диске, ..)в виде букв и цифр. Также А. - программа, которая переводит асм в М. К.
ЛАМЕР - не КОДЕР. Также Л. - тот, кто любит портить чужие программы.
ХАКЕР - хороший КОДЕР, который изменяет чужую программу в лучшую сторону (например, вставляет вечную жизнь, красивую заставку, упаковывает игру, редко - исправляет ошибки в программе или добавляет к ней новые возможности).
ПАМЯТЬ - память компьютера. В более узком смысле - оперативная память(ОЗУ, в нее еще можно записывать).
БАЙТ - символ/ число от 0 до 255/ число от -128 до 127, причем -128 соответствует 128, -127 соответствует 129, и. т.д. Из них состоит память.
БИТ - одна восьмая байта. Содержит минимум информации:0 или 1. (Несмотря на бесконечные повторения этой бессмысленной фразы в литературе, спешу сообщить, что минимум информации - это ноль бит, а если Вы скажете, что так не считается, то приведу еще пример меньшей информации:0 с вероятностью 1/3 или 1 с вероятностью 2/3.) Нумеруются в байте справа налево с нуля, причем сумма битов, помноженных на двойки в степени их
номеров, даст значение байта.
Лучшим Ассемблером является ALASM.
Он имеет 2 режима - командный и редактирования. Первый устанавливается после загрузки. Вход во второй - набрать EDIT (кнопка Е) название. Например: EDIT ААА.
Тут же Вы войдете в новоиспеченный текстовый файл ААА. H и сможете его изменить.
Теперь Вы сидите перед экраном, а голова Ваша почему-то стала плохо соображать. В таких случаях я набираю первую и последнюю строчки будущей программы. Вот как они обычно выглядят:

Код: Выделить всё
ORG 25000
RET
Первая указывает место в памяти, где будет работать программа (от 24576 до 65535) и не является командой процессору (то есть не занимает места). Последняя - выход из программы(или из подпрограммы, что в сущности то же самое)туда, откуда ее осмелились запустить(вызвать).
Команды типа ORG называются директивами Ассемблера. Еще пример директивы:

Код: Выделить всё
ENT
Она нужна для того, чтобы знать, с какого места запустить Вашу изобилующую ORG'ами программу, поскольку одни Ассемблеры (MASM) предпочитают последний ORG, другие (ALASM) - первый, а некоторые - вообще отказываются транслировать(ассемблировать)программу без ENT или ENT $.
Строчки для вставления команд в середину текста раздвигаются кнопками SS+W (<>), а сдвигаются кнопками SS+Q (<=). Сначала это может показаться неудобным, но потом Вы найдете это весьма хорошим способом.
Полезна директива

Код: Выделить всё
DEFB "text", #3F, 5, "a"
Она засовывает в то место памяти, где должна была бы располагаться следующая команда программы, любой набор байтов (символов). Аналогична команда DEFW, но она сует байты по два и не переваривает текстов.Еще загадочнее команда DEFS 40, 1, 2, 3 - которая 40 раз подряд пихает в память байты 1, 2, 3. Решетка # означает шестнадцатиричное число #3F=3*16+F, где A, B, C, D, E, F соответственно равны 10, 11, 12, 13, 14, 15.
Но я отвлекся. Чтобы наша программа делала хоть что-то, хотя мы еще ничего не умеем, нагло используем какую-нибудь чужую программу из ПЗУ (там много интересного):

Код: Выделить всё
ORG 25000
CALL 3582
RET
Теперь мы вызываем программу сдвига всего экрана вверх на знакоместо(SCROLL UP CHR$) таким же образом, как нашу программу вызвала система (Бейсик, ALASM, TR-DOS, ...).
Чтобы запустить сей плагиат(дедовщину?) и посмотреть, как он работает, выйдем из режима редактирования в режим команд. Для этого нажмите EXTEND;появится строчка ожидания команды редактора. Можно ввести разные команды: B - начало текста, E - конец, S - поиск чего-нибудь, X - замена, и еще уж не помню что, но Вам надо нажать Q - Quit.
Теперь программу стоит записать: SAVE. После этого ассемблируем: ASSEMBLE и запускаем: RUN. Экран сдвинулся вверх, ура.
Можно также вызвать ее из Бейсика: QUIT (выход в Бейсик), RANDOMIZE USR 25000.
Возврат в ALASM - RANDOMIZE USR 23600.
Из встроенного отладчика StS: DEBUG (отладка), JUMP 25000. RANDOMIZE USR 23600. Переход в редактирование - EDIT.
Для полного овладения системой Вам стоит прочитать HELP'ы к ALASM и StS. Дальнейший текст для компактности предполагает, что Вы уже умеете с ними обращаться.

Глава 2
обо всём понемножку

Регистр является маленькой переменной, которая хранится не в памяти, а в процессоре. В регистре 1 байт. Названия регистров:

Код: Выделить всё
A
B C
D E
H L
Я перечислил только регистры общего назначения, всего же регистров 24. 6 последних собраны в пары, которые называются просто "регистровыми парами" (reg pair, rp) и могут использоваться как двухбайтное число/адреc (из 160К памяти одновременно адресуются 64К, посему адрес байта передается 2 байтами) Регистру можно присвоить значение командой

Код: Выделить всё
LD E, 100
или LD BC, 40000
или LD A, H
но не LD HL, BC
Метка (label)аналогична номеру строки в Бейсике за тем ислючением, что ее не нужно помещать в каждой строке. Метку можно использовать в выражениях вместо соответствующего числа. Метка содержит 7 символов и начинается с буквы. Пример:

Код: Выделить всё
ORG 25000
LD DE, TEXT
LD BC, TEND-TEXT
CALL #203C ;опять программа из ПЗУ
RET
TEXT DEFB "TEXT - это метка", 13
TEND
Печатается текст по адресу TEXT=25010 длиной TEND-TEXT=17 байт. Все эти вычисления производит ALASM при трансляции.
Если Вы не желаете, чтобы программа выполнялась только подряд, можно использовать переход к метке:

Код: Выделить всё
ORG 25000
LD BC, #50F0; B=#50=80, C=#F0=240
JP 8933
На экране появляется точка. JP 8933 передает управление программе в ПЗУ, которая, естественно, уже содержит RET, так что можно не волноваться по поводу возврата. Переход не более чем на 127 байт вперед/назад называется коротким или относительным и записывается JR адрес.
Когда нужно выполнить что-то несколько раз подряд(совершить цикл), в частности, используется команда DJNZ адрес:

Код: Выделить всё
ORG 25000
LD B, 80
CYCLE LD (BUF), BC;запишем;8933 портит B
LD C, B
CALL 8933
LD BC, (BUF);в BC старое значение
DJNZ CYCLE
RET
BUF DEFW 0
Нарисуется диагональ. DJNZ вычитает из B единицу и, если не получился ноль, переходит по указанному адресу. Легко подсчитать, что поэтому цикл выполнится ровно столько раз, сколько было в B при входе в него(т.е. 80). Круглые скобки означают, что имеется в виду не число, а ячейка памяти с этим номером. LD (BUF), BC записывает BC по адресу BUF.
Использовать ячейки с метками для хранения регистров неудобно, поэтому придуманы команды: PUSH rp(пихнуть) и POP rp(вытолкнуть). Первая запоминает rp в области памяти, именуемой стеком, вторая берет оттуда текущее значение в rp. Много значений, засунутых в стек, снимаются оттуда в обратном порядке. Там же хранится адрес, по которому переходит команда RET. Поэтому число PUSH и POP должно совпадать. Пример:

Код: Выделить всё
ORG 25000
LD B, 80
CYCLE PUSH BC
LD A, 80
SUB B
LD C, A
CALL 8933
POP BC
DJNZ CYCLE
RET
Нарисуется обратная диагональ. Команда SUB r относится к категории арифметическо-логических и вычитает из A регистр r. Другие а-л команды:
ADD A, r;прибавить r к A
ADD HL, rp;прибавить rp к HL
ADC A, r;A=A+r+CY
ADC HL, rp;HL=HL+rp+CY
SBC A, r;A=A-r-CY
SBC HL, rp;HL=HL-rp-CY
DEC r/rp;уменьшить rp на 1
INC r/rp;увеличить rp на 1
AND r;побитовое A И r записывается в A. Обнуляются все биты A, которым соответствуют нулевые биты r.
OR r;побитовое A ИЛИ r записывается в A. В единицу обращаются все биты A, соответствующие которым биты r были равны 1.
XOR r;то же, но побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ. B каждый бит A записывается 1, если биты с этим номером в A и r были разные;иначе 0.
CP r;сравнение A с r
CPL;A=255-A. Все биты инвертируются(0 1)
NEG;А=-А.
DAA;Двоично-десятичная коррекция; производите ее сразу после сложения/вычитания, если с/в'емые числа были двоично-десятичные. Вряд ли она Вам пригодится, т.к. д-д числа - это метод записи двух цифр в байте, причем д-д #34 считается равным 34.
Несколько слов о том, что же такое CY. Он называется флагом(признаком, битом)переноса и устанавливается в 1, если результат сложения превысил 255(65535 в случае 2-байтового сложения) или при вычитании большего числа из меньшего или в других особо оговоренных случаях. Еще используется флаг Z, который равен 1, если результат а-л операции равен нулю, и нулю в других случаях. За это он называется флагом нуля. Все флаги находятся в регистре флагов F, который вместе с регистром A составляет еще одну(четвертую)r.p. AF, которая, к сожалению, не может использоваться в двухбайтовых вычислениях.
Сравнение - то же вычитание, но результат его не запоминается, а только соответствующим образом меняются флаги:
Z=1, если A=r;Z=0, если A<>r;
CY=1, если A<r;CY=0, если A>=r.
Зачем нужны флаги? Да для того, чтобы по ним потом получать условия ветвления программы, вызова последней или выхода из нее. Команда условного короткого перехода выглядит так: JR cc, <метка>, где cc - условие:
Z - Z=1 Поскольку есть еще флаги, то есть
NZ - Z=0 и дополнительные редко использу-
C - CY=1 емые условия, употребляемые в ко-
NC - CY=0 мандах длинного перехода JP.
То есть, если условие выполнится, то следует осуществить переход, иначе - нет.

Глава 3
несколько важных практических советов

Программа становится Вашей лишь тогда, когда Вы трудились над ее созданием. Кстати, не стоит также радоваться после написания любой программы, если последняя до Вас была написана хотя бы одним человеком.
Существует два способа написания программ на асме: на бумаге ручкой/карандашом с последующим набором на компьютере и непосредственно сидя за/перед экраном. Первый способ хорош тем, что можно писать программы вдали от компьютера и плох низкой производительностью и повышением числа ошибок; второй обходит недостатки первого и теряет его достоинства. Желательно владеть обеими.
Несмотря на то, что Пентагон 128-й, помните, что не каждый компьютер - Пентагон. Следовательно, не стоит пользоваться двумя экранами, когда довольно одного, а также жрать все 71680 тактов процессора или ставить первой командой прерывания EI.
НИКОГДА не управляйте включением/выключением дисковода для проверки наличия диска или проигрывания через дисковод музыки! В отечественном дисководе 5313 при этом нарушается работа механизма опускания головки на диск и дисковод НЕ МОЖЕТ ПИСАТЬ ИНФОРМАЦИЮ!
Имейте копии своих важных программ на своих и/или чужих дисках. Последнее иногда даже надежнее. Не имейте копий барахла. Сохраняйте системную дорожку.
Экономьте свое время, e.g. не смотрите дважды одни и те же телепередачи, не ходите на дискотеки и пьянки. Помните: жизнь у человека одна и короткая, а вспомнят о Вас лишь если Вы успеете сделать за нее много. Научитесь говорить, печатать, ходить и думать быстро.
Имейте терпение; ошибки в программах случаются и у мэтров из CodeBusters, но они умеют их исправлять=>и Вы научитесь. Сперва структуру сложной программы Вы не сумеете удержать в памяти, но через небольшое время регулярной работы на компьютере размер программы, набираемой зараз, станет неограниченным.
Не составляйте программу из кусочков!
Метки в программах рекомендуется придумывать так: название подпрограммы+буква/цифра, например: MOVTXT0 в п/п MOVTEXT; READKYQ в READKEY; можно SYMN13 в SYM.
Если кто-то скажет Вам, что некий метод является всегда лучшим, не верьте ему. Для примера возьмем перемещение памяти. Медленный LDIR незаменим в текстовом редакторе; LDI весьма полезен при вертикальном сдвиге экрана и недостатке памяти под сдвигалку; POP HL:LD (...), HL используется в сдвигах, мультиколорах и мэппингах;POP rp...PUSH rp хорошо для ускорения мэппинга (см. статью в следующем номере); LD rp, ...PUSH rp доселе использовалось только для рисования сеточек, хотя одним махом увеличивает ширину мультиколора до 24 CHR$ +позволяет вывести экран в одно прерывание (см. статью).
Несмотря на то, что переключение двух изображений дает разнообразные графические режимы, помните, что это приводит к мерцанию экрана, которое, возможно, годится для демо, но не для программы, которую пользователь активно использует. Можно даже вспомнить: Quo vicet Iovi, non licet bovi, что означает "Что может Юпитер, то не позволено быку". Переключение трех экранов не используйте никогда, поскольку это влечет за собой не мерцание, но моргание экрана.
Не ограничивайте сложность составляемых Вами программ, оправдываясь тем, что некто является очень умным или у него больше свободного времени, чем у Вас. Не боги горшки обжигают! У меня вообще нет свободного времени, однако написал же я этот журнал!

Урок ассемблера для ламеров
(продолжение)

Сегодня я собираюсь рассказать вам о методах опроса клавиатуры, прерываниях, а также постараюсь исправить свои ошибки, которые допустил в предыдущем номере.

1. Начну с ошибок.

В прошлый раз я так страшно загрузил вас описанием директив ассемблера, причём весьма неполным и ошибочным описанием. Но если вы внимательно читали текст об ALASM, то, скорее всего, пропустили этот бред мимо ушей. Дальнейшее относится к тем другим, кто поверил этому бреду и не читал описания. Во избежание.
Нельзя сказать, что директива не занимает места в памяти. Взять хотя бы DEFB (DB): она, конечно же, не является командой процессору, но память жрёт честно:ровно столько, сколько байт информации после неё записано. Или другая директива:

Код: Выделить всё
DUP 8
RR C
RLA
EDUP
После компиляции этот кусок будет выглядеть так:

Код: Выделить всё
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
Мало того, что он занимает больше памяти, чем просто

Код: Выделить всё
RR C
RLA
Ведь при этом вся эта память заполняется сплошь командами процессора!
Насчёт директивы ENT я написал полную ерунду. Скажу честно:это потому, что я тогда ещё не разу её не использовал. На самом деле эта директива ходит в паре с DISP и ограничивает снизу кусок, которому DISP сверху приписала работать в других адресах (а не по тому адресу, по которому этот кусок компилируется). Пример:

Код: Выделить всё
ORG #6000
LD HL, KUSOK
LD DE, #4000
PUSH DE
LD BC, KUSEND-KUSOK
LDIR
RET
KUSOK DISP #4000

<какая-то программа, сплошь напичканная CALL, JP и т.п., и потому неперемещаемая>

ENT
KUSEND
Кстати, если метки KUSOK и KUSEND вставить внутрь блока DISP-ENT, то эти метки, так же как и все остальные в этом блоке, будут пересчитаны, и, естественно, будут содержать совсем не те значения, какие бы нам хотелось.
В директиве ORG допустимо два параметра, причём если их два, то второй - это номер странички, куда мы компилируем. А программа запускается, между прочим, не по первому ORG, а по последнему!
Директива INCLUDE <имя>[, <страничка>] служит для подгрузки модулей для длинных программ. При компиляции ассемблер, натыкаясь на эту директиву, подгружает соответствующий файл (если его ещё нет в памяти), компилирует его, и только затем продолжает компиляцию основной программы с того места, где она была прервана.
Директива INCBIN <имя>[, <страничка>] подгружает кодовый файл (кстати, можно указыать расширение через точку) по текущему адресу компиляции, и перемещает этот адрес компиляции на конец этого файла.

2. Опрос клавиатуры.

Клавиатура старого ZX Spectrum 48k содержала 40 клавиш. Остальные клавиши расширенной клавиатуры являются их сочетаниями, например BREAK=CAPS/SPACE, EXTEND=CAPS/SYMBOL, TRUE VIDEO=CAPS/3 и т.д.
40 клавиш собраны в 8 полурядов по 5 клавиш в каждом:


Код: Выделить всё
#F7FE: 1 2 3 4 5 #EFFE: 6 7 8 9 0
#FBFE: Q W E R T #DFFE: Y U I O P
#FDFE: A S D F G #BFFE: H J K L Enter
#FEFE:CapsZ X C V #7FFE: B N MSymSpace

Через некоторое время я объясню, что это за числа слева, но сперва расскажу о том, как процессор работает с периферийными устройствами (т.е. вообще со всеми устройствами, кроме памяти).
Устройства выбираются при IORQ=0 (т.е. когда этот сигнал активен). Далее устройства, в которые записывают, должны проверить, что WR=0 (т.е. активен сигнал записи), а устройства, из которых принимают данные, проверяют, что RD=0 (активен сигнал чтения), а потом, все устройства проверяют определённую комбинацию адресных сигналов, которая у каждого устройства своя. Например, пищалка (BEEPER) выбирается при A0=0.
Откуда берутся эти сигналы? Естественно, с процессора. Комбинация

Код: Выделить всё
IORQ=0, WR=0
вырабатывается при командах OUT, а комбинация

Код: Выделить всё
IORQ=0, RD=0
- при командах IN.
Вроде бы, мы об этих командах ещё не говорили. Итак:
OUT (<байт>), A - записать аккумулятор в порт, адресом которого служит: A (старший байт)*256+<байт> (младший байт). Содержимое аккумулятора выводится на шину данных. Адрес порта, естественно, выводится на шину адреса.
OUT (C), <регистр> - записать регистр в порт, адрес которого содержится в регистровой паре BC. Регистром может быть:A, B, C, D, E, H, L.
OUT (C), 0 - записать ноль в порт BC. Команда недокументирована, многими ассемблерами не поддерживается. На процессоре Z180 приводит к сбросу.
IN A, (<байт>) - считать из порта данные в аккумулятор. Адрес порта =A*256+<байт>.
IN <регистр>, (C) - считать в регистр данные из порта BC.
IN F, (C) - считать данные из порта BC без запоминания. Вместо этого соответствующим образом устанавливаются биты флагового регистра. (Каким таким образом они устанавливаются, не знаю. У Ларченко и Родионова не уточняется.) Команда недокументирована. В некоторых ассемблерах она записывается как IN (HL), (C).
Команды IN r, (C) и OUT (C), r называются обращением к порту с полной адресацией, в отличие от неполной адресации OUT (b), A. Ко многим портам (в том числе, к музыкальному сопроцессору AY) можно обращаться только с полной адресацией.
Существуют также команды блокового обращения к портам. Мне как-то не приходилось их использовать.
Те загадочные числа, которые я привёл против названий клавиш в полурядах, являются как раз адресами соответствующих портов. А считать из этих портов можно следующую информацию:
бит 7 - не определён;
бит 6 - чтение с магнитофона. На многих компьютерах не реализовано. На некоторых оно реализовано так, что оттуда считываются случайные значения (из-за того, что я забыл замаскировать этот бит по AND, в первом номере журнала жутко колбасила стрелка);
бит 5 - не определён;
биты 4-0 - состояния клавиш полуряда. Если клавиша нажата, считывается 0, а в противном случае - 1. Более младшие биты относятся к более крайним клавишам.
Пример использования:

Код: Выделить всё
START CALL <подпрограмма>
LD A, 239 ;старший байт полуряда 6-0
IN A, (254) ;считываем данные
RRA ;0-й бит переходит в CY
JR C, START ;крутим, пока не нажмут 0
На самом деле каждый порт клавиатуры выбирается по двум сброшенным битам:биту 0 и ещё какому-то в пределах от 8 до 15. Если сбросить несколько старших битов, выберутся сразу несколько полурядов, и их содержимые наложатся по AND. Пример:

Код: Выделить всё
LOOP XOR A ;все биты сброшены
IN A, (254) ;опрашиваем все полуряды
CPL ;почти эквивалентно комбинации:
AND 31 ; AND 31:CP 31, но короче
JR Z, LOOP ;пока не нажмут ANY KEY
Другим методом опроса клавиш является использование подпрограмм ПЗУ и результатов работы прерывания IM 1. Например, процедура 8020 сбрасывает CY, если нажат BREAK. А работать с IM 1 можно таким образом:

Код: Выделить всё
RES 5, (IY+1) ;сброс флага "ANY KEY"
NOKEY HALT ;если убрать HALT, может подви-
BIT 5, (IY+1) ;снуть на нек. компах!
JR Z, NOKEY ;пока не нажмут что-либо
LD A, (23560) ;сист.переменная LAST_K
В результате в аккумуляторе будет код последней нажатой клавиши. Будьте осторожны: если установлен режим CapsLock, то вы будете считывать оттуда сплошь большие буквы! А установить CapsLock можно так:

Код: Выделить всё
LD (IY+48), 8 ;сист. переменная FLAGS2
В своём AC Edit я успешно комбинирую оба способа опроса клавиш.

3. Некоторые другие порты.

Тот же порт (254), выбранный на запись, отвечает за изменение цвета бордюра, пищалку и вывод на магнитофон. Биты у него такие:
биты 7-5 - не используются;
бит 4 - состояние пищалки. Чтобы вызвать звук, необходимо постоянно переключать этот бит;
бит 3 - вывод на магнитофон;
биты 2-0 - цвет бордюра. У бордюра может быть 8 различных цветов. Яркость в этих цветах отключена. Чтобы получать на бордюре статичные картинки, нужно каждый раз от начала кадрового прерывания изменять определённым образом этот цвет, пока электронный луч прорисовывает экран.
Пример:

Код: Выделить всё
XOR A ;чёрный цвет
OUT (254), A ;бордюр станет чёрным

Порт 31 (#1F) на чтение повествует о состоянии кемпстон-джойстика:
биты 7-5 - всегда равны 0, если джойстик подключен, а в противном случае об их состоянии нельзя сказать ничего определённого;
бит 4 - огонь (1 - нажат, 0 - отпущен);
бит 3 - вниз (аналогично);
бит 2 - вверх;
бит 1 - вправо;
бит 0 - влево.

Порт 32765 (#7FFD) - порт расширенной памяти (на запись). На чтение невозможен (Кроме нескольких патологов). Назначение битов:
биты 7-6 - на 128k не используются;
бит 5 - защёлка порта #7FFD. Если этот бит установить, компьютер становится сорок восьмым со всеми вытекающими из этого последствиями. После сброса всё приходит в норму;
бит 4 - если 0, то в адресах 0-16383 будет торчать 128-е ПЗУ. Обычно это не нужно, и этот бит устанавливают в 1, тогда в нижних адресах будет 48-е ПЗУ;
бит 3 - номер экрана: если 0 - то обычный "первый" экран 16384-23295 из странички № 5, иначе - "второй" экран из странички номер 7;
биты 2-0 - номер странички памяти, которая будет помещена в область 49152-65535. Здесь нужно остановиться подробнее.
Всего у 128k, как можно догадаться, 8 страничек ОЗУ по 16k. От 16384 до 32767 всегда находится страничка № 5, от 32768 до 49151 - страничка № 2, а вот выше - уже любая, какая вам нравится (включая 2 или 5). По выходе из ассемблера устанавливается страничка № 0, сам ассемблер в № 4, монитор в № 7, а текст вашей программы, скорее всего, в № 6. Страничку № 3 ассемблер использует под таблицу меток. Итак:
Если вы не собираетесь использовать монитор, смело затирайте странички № 3 и № 7. (Только не ассемблируйте на № 3 и на № 7 с #C000 по #C8FF, т. к. она используется как буфер при подгрузке с диска.) Странички №№0, 1 безусловно свободны. А если вам стало уж совсем тесно, можете затирать и ассемблер вместе с исходником (соответственно №№4, 6).
Есть, конечно, Spectrum'ы и с большим объёмом памяти (до 2 Mb), но распространены они мало. Так что писать под них не стоит, тем более что всё равно вы не сможете сполна использовать все возможности расширенной памяти, не имея таковой.
В связи с большим количеством разнообразных патологов с разными вариантами дешифрации порта #7FFD, возникла так называемая проблема порта #FD. Название её связано с тем, что на компьютерах "Пентагон-128" дешифрация порта расширенной памяти осуществляется всего по 2 битам: A1 и A15, в результате чего к этому порту стало возможно обращаться по неполной адресации:

Код: Выделить всё
LD A, 23 ;7-я страничка
OUT (#FD), A ;записываем её № в порт
Вы не находите, что это несколько удобнее, чем

Код: Выделить всё
LD A, 23
LD BC, 32765
OUT (C), A
Вот так многие и подумали, и во многих программах (например, by CodeBusters) стоит именно неполная адресация порта. Разумеется, на некоторых компьютерах такие программы не работают. Например, вышеизложенный пример на "Скорпионе" воспримется как обращение к порту #1FFD, а это уже, понятно, совсем другой порт (переключение TURBO, включение в область 0-16383 страницы теневого ОЗУ № 8, переключение теневых страниц
ОЗУ, ПЗУ и ещё неизвестно чего).
Я считаю (и многие другие тоже так считают), что все Спектрумы равноправны, и если программа не работает кое-где из-за такой мелочи, как неполная дешифрация портов, то это плохая программа. Разумеется, некоторые вещи, например, цифровую музыку с высоким качеством, можно реализовать только на некоторых типах Спектрумов ("Пентагон", KAY, ATM и т.п.), но это совсем другая проблема. Это пусть вам дядя Зонов объясняет, зачем в его компьютерах процессор тормозится при общем поле памяти. А если говорить по общему счёту, то если поддерживать только "Пентагон"(говорю это несмотря на то, что у меня самого "Пентагон"), то синклеристы, пользующиеся другими типами Спектрумов (а их не меньше 40%) могут серьёзно обидеться и уйти со Спектрума. Хорошо нам от этого будет? Вот так-то. Между прочим, даже демки теперь работают на "Скорпионах". Учитесь!

Порты 65533 (#FFFD), 49149 (#BFFD) отвечают за доступ к музыкальному сопроцессору AY. У сопроцессора 16 регистров разного назначения. Для того, чтобы записать что-то в какой-либо из них, нужно заслать его номер в порт 65533, а потом данные, предназначенные для этого регистра, спустить в порт 49149. Если надо, наоборот, считать данные, то после записи № регистра в порт 65533 нужно считать данные из того же порта 65533. Все анализаторы громкости во всяких там boot'ах основаны именно на чтении из AY. Назначение отдельных регистров:

Код: Выделить всё
№№ 0, 1 - содержит 12-разрядный период (не частоту, а именно период!) ноты в канале A. Причём регистр 1 - старший;
№№ 2, 3 - период канала B;
№№ 4, 5 - период канала C;
№ 6 - пятиразрядный период шума;
№ 7 - управление звуком:
биты 6, 7 - указывают направление обмена по параллельным портам, и посему нас не интересуют;
биты 3-5 - если 1, то запрещён вывод шума соответственно в канал A, B, C;
биты 0-2 - если 1, то запрещён вывод ноты в канал A, B, C. Зато взамен, если манипулировать громкостью в соответствующем канале, можно получить цифровую музыку! А если включена огибающая, то она будет звучать сама по себе!
№ 8 - 4-битная громкость канала A. Заметьте, что шкала громкости не линейная, а, скорее, логарифмическая. Если установить 4-й бит этого регистра, то громкости уже не будет, а взамен будет накладываться огибающая;
№№ 9, 10 - аналогично для каналов B, C;
№№ 11, 12 - период огибающей. При проигрывании звука на огибающей используется только младший байт (№ 11);
№ 13 - 4-битная форма огибающей:
0 - плавное затухание до нуля;
12 - пилообразный звук;
13 - плавное нарастание до максимума;
14 - зигзагообразный звук на октаву ниже, чем 12;
№№ 14, 15 - используются для обмена по параллельным портам.
Конечно, вряд ли вы будете сами играть музыку через прямое обращение к AY, так что в качестве примера покажу только, как выключить звук:

Код: Выделить всё
LD DE, #E00
LD C, #FD
OFF0 LD B, #FF
DEC D
OUT (C), D ;выбираем № регистра
LD B, #BF
OUT (C), E ;записываем в него ноль
JR NZ, OFF0 ;и так до 0-го регистра

4. Прерывания.

Каждые 20 миллисекунд (1/50 секунды) на процессор приходят кадровые прерывания. Это выражается в том, что на ножку INT подаётся отрицательный импульс. Длина импульса, как водится, у каждого патолога своя, но не будем об этом.
Если во время прихода импульса были включены прерывания (командой EI, выключаются же они командой DI), то, в зависимости от текущего режима прерываний, процессор начнёт выполнять:
а) (режим IM 0) команду, которая пришла с шины данных (не используется);
б) (режим IM 1) подпрограмму RST 56;
в) (режим IM 2) подпрограмму, адрес которой он прочитает из ячейки с адресом: I*256+<шина данных>, где I - регистр вектора прерываний.
В любом случае перед входом в подпрограмму обработки прерываний процессор отключает прерывания.
В настоящий момент нас более всего интересует режим IM 2, т.к. в этом режиме можно вставить собственный обработчик.
Поскольку состояние шины данных не определено в общем случае (т.е. не на всех компьютерах оттуда считывается стабильно 255), то желательно, чтобы адрес обработчика не зависел от состояния шины данных . Это достигается однородным заполнением одинаковыми числами так называемой таблицы прерывания, длиной 257 байт (для каждого из 256 возможных состояний ШД из таблицы считываются 2 одинаковых байта). Причём таблицу эту следует размещать в так называемой быстрой памяти (странички № 0 или № 2), а то некоторые патологи могут подвиснуть... Пример:

Код: Выделить всё
MUZ EQU #C000
ORG MUZ
+ INCBIN "MUSIC"
ORG #6000
DI
CALL MUZ ;инициализируем музыку
LD HL, #FE00
LD A, H
LD I, A ;I=#FE
LD DE, #FE01
LD BC, #100
LD (HL), #5C
LDIR ;заполняем таблицу прерывания
LD L, (HL)
LD H, L ;HL=#5C5C
LD (HL), 195 ;JP
INC HL
LD (HL), IMER
INC HL
LD (HL), 'IMER
IM 2
EI

<далее программа будет работать под музыку>

IM 1 ;выключаем IM 2
JP MUZ ;выключаем музыку и выходим

IMER PUSH AF
PUSH BC
PUSH DE
PUSH HL
PUSH IX
PUSH IY
CALL MUZ+5 ;вызываем музыку
POP IY
POP IX
POP HL
POP DE
POP BC
POP AF
EI
RET
То есть, если повесить на прерывание какое-либо действие (например, проигрывание музыки), то программа уже не должна будет за этим следить, и мы получаем некоторое подобие многозадачности (много-, а не дву-, потому что никто не мешает нам повесить на прерывание несколько разных задач, например, музыку и мультиколор).
Со включенным прерыванием нельзя входить в TR-DOS, иначе при первом же вызове прерывания TR-DOS исчезнет, и на её месте окажется BASIC. И при возвращении из прерывания мы попадём немного не туда . Способ, как обойти это, указан в книге "TR-DOS для пользователей и программистов". На самом деле всё это не нужно. Просто отключайте прерывания при входе в TR-DOS.
Если не хватает места под таблицу прерывания, поместите её в медленную память, например, по адресу #5B00. Но учтите, что тогда ваша программа будет работать не везде. Если и в медленной памяти нет места, можете оставить от таблицы всего 2 байта по адресу I*256+255 (так сделано в TLW2). Этим вы ещё сильнее уменьшаете число своих пользователей. Самый последний вариант: I=59. Тогда таблица (длиной 257 байт для 48k, или 2 байта для 128k) будет в ПЗУ, а процедура обработки прерываний - по адресу 65535. Поставьте туда JR, а по адресу 65524 (куда указывает JR) поставьте обработчик. Теперь работоспособность вашей программы, помимо модели компьютера, ограничена ещё и версией ПЗУ...

5. Полезные советы.

Лучше всего начинать набирать программу со строк:

Код: Выделить всё
ORG #6000
LD (QUIT+1), SP

QUIT LD SP, 0
LD IY, 23610
IM 1
LD HL, 10072
EXX
EI
RET
END
Кто знает, какие регистры может испортить ваша программа, пока она ещё глючит? А метка END позволяет вам всегда узнать длину программы. Для этого после ассемблирования в командном режиме введите: COUNT END-#6000
Советую также поставить в программу подпрограмму печати 16-разрядных чисел и вызывать её время от времени в главном цикле работы программы. Это позволит вам контролировать зависание. Подпрограмму см. в разделе "Этюды".
Пишите программу красиво и удобно для исправления. Чаще используйте CALL. Выделяйте законченный функциональный блок в подпрограмму, даже если он вызывается только один раз. Сохраняйте регистры в подпрограммах. Не думайте о перемещаемости, используйте JP вместо JR.
Все адреса таблиц, музыки, спрайтов и др. заносите в EQU. Это позволит вам легко сменить эти адреса, если что. Последние опыты показали, что даже номера используемых страниц памяти могут измениться, и их тоже надо заносить в EQU.
Когда ваша программа превысит 4k (а у меня уже 3 таких программы), её текст начнёт не помещаться в 16k-буфере. Придётся выделить модуль и подгружать его по директиве:

Код: Выделить всё
INCLUDE "MYUNIT", 1
Подгружаться он будет в другую страничку, и это позволит вам одновременно редактировать оба текста. Для модуля следует отбирать подпрограммы, которые вам не приходилось исправлять долгое время (я называю их "бессмертными").
Подгружайте INCBIN'ом данные в странички разве что только во время отладки. Лучше всего подгружать их непосредственно на хвост программы, а потом перекидывать LDIR-'ом. Тогда программу будет легче отгрузить в откомпилированном виде и запаковать. Стоит ли говорить о том, что прогу, раскиданную по страничкам, запаковать вообще ни в одном упаковщике нельзя?

Урок ассемблера для ламеров.
(продолжение)
(C) N!KPhE/Invaders9 (30982b)

Ко всем на удивление, этот третий номер будет вести N!KPhE. Постараюсь всё излагать понятно и правильно. Посмотрим, какой из меня педагог .
Начнём с самого главного, без знания чего писать программы просто невозможно.

Глава 1 "ЭКРАH"
1 "Экранная область"

Мне теперь понятно почему Alone Coder бросил написание этой статьи: он знал, что объяснить простому ламеру строение экранной области - невозможно! Но деваться некуда... =8-[ ]
Размер экрана в нашем Speccy составляет ни много, ни мало, а 256 точек/пиксел/бит по горизонтали и 192 по вертикали. Каждые 8x8 пикселов - это одно знакоместо. Таким образом, экран делится на 24 символьные строки по 32 знакоместа в каждой.
Экранная область в целом делится на две части:
основной экран.......[#4000-#57FF] (6144b)
атрибуты.............[#5800-#5AFF] (768b).
Каждый байт состоит из восьми бит/пикселов (нумерация идет справа налево):

Код: Выделить всё
+-+-+-+-+-+-+-+-+
|7|6|5|4|3|2|1|0| <-структура байта
+-+-+-+-+-+-+-+-+
Сумма битов, помноженных на двойку в степени их номеров, даст значение байта.
Основной экран делится на три абсолютно равных сегмента (по 2048 байт каждый):
первый сегмент...............[#4000-#47FF]
второй сегмент...............[#4800-#4FFF]
третий сегмент...............[#5000-#57FF]
Для того, чтоб лучше понять, приведу маленький кусок верхнего края первого сегмента

Код: Выделить всё
+-----+-----+-----+-----+-----+-----+-----
|#4000|#4001|#4002|#4003|#4004|#4005|#40 06
|#4100|#4101|#4102|#4103|#4104|#4105|#41 06
|#4200|#4201|#4202|#4203|#4204|#4205|#42 06
|#4300|#4301|#4302|#4303|#4304|#4305|#43 06
|#4400|#4401|#4402|#4403|#4404|#4405|#44 06
|#4500|#4501|#4502|#4503|#4504|#4505|#45 06
|#4600|#4601|#4602|#4603|#4604|#4605| ...
|#4700|#4701|#4702|#4703|#4704| ... | ...
+-----+-----+-----+-----+-----+-----+---
|#4020|#4021|#4022|#4023| ... | ... | |
|#4120|#4121|#4122| ... | ... | ... |
|#4220|#4221| ... | ... | ... | ... |
|#4320| ... | ... | ... | ... |#45FF|
| ... | ... | ... | ... |#46FE|#46FF|
| ... | ... | ... |#47FD|#47FE|#47FF|
------+-----+-----+-----+-----+
Один адрес - это байт. Одна клетка - это знакоместо. Упорядочные клетки по вертикали - это столбец, по горизонтали - строка.
Так как я сильно сомневаюсь, что вы что-то здесь поняли, я приведу простую прогзу в БЕЙСИКЕ, которая последовательно заполняет экранную область байтом 255(все восемь бит включены, т.е. равны единице). С её помощью вы сможете разобраться поточнее (хотя, чтобы как следует понять структуру экрана, надо с ним работать)

Код: Выделить всё
FOR A=16384 TO 22527:POKE A, 255:NEXT A
С областью атрибутов проще. Каждый атрибутный байт (цвет) привязан к соответствующему знакоместу. Начинается область атрибутов с адреса #5800 и на экране проходит "линейно", т.е. она идентична декартовой системе (которую проходят в школе) с тем отличием, что начало координат расположено в верхнем левом углу.
Можно вывести простую формулу расчёта адреса атрибута по заданным (X, Y) координатам: ATTR=Y*32+X+#5800.
Структура атрибутного байта:

Код: Выделить всё
+-+-+-+-+-+-+-+-+
|7|6|5|4|3|2|1|0|
+-+-+-+-+-+-+-+-+
биты 0..2 - цвет тона (INK)
биты 3..5 - цвет фона (PAPER)
бит 6 - яркость для тона и фона (BRIGHT)
бит 7 - мерцание (FLASH)
Напоследок в эту главу приведу процедурку, которая выставляет цвет по заданным X, Y координатам в знакоместах:

Код: Выделить всё
LD HL, Y*256+X ;H=Y, L=X
LD A, H
AND 7
RRCA
RRCA
RRCA
ADD A, L
LD L, A
LD A, H
RRA
RRA
RRA
AND 3
OR #58
LD H, A
LD (HL), COLOR
Совсем забыл:в экранной области есть ещё одна, третья, область, которая значительно отличается от других. Называется она бордюр (BORDER). Она не имеет ни каких привязанных адресов, но может принять один из восьми цветов:

Код: Выделить всё
LD A, COLOR ;цвет (0-7)
OUT (#FE), A
Подробней про него можно узнать во втором уроке для ламеров (ZX-Guide'2).

Глава 2 "Флаги"
2 "Влияние на флаги"

Сначала я не хотел очередной раз упоминать о них, но узнал, что некоторые начинающие кодеры и представления не имеют о флагах и уж тем более об их использовании.
Попал я как-то на корабль, где был флажок с черепком и костяшками .
Флаг устанавливается для пометки выполнения определённого условия, т.е. даёт информацию о только что выполненном вычислении.
В нашем Speccy, вернее, в центральном процессоре Z80, есть специальный регистр F (флаговый), который хранит в себе шесть флагов:

Код: Выделить всё
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
| S | Z |###| H |###|P/V| N | CY|
+---+---+---+---+---+---+---+---+
Флаг считается установленным, если в соответствующем бите записана единица, и сброшенным, если записан ноль.
Z(zero) - флаг нуля. станавливается, если результат операции равен нулю.
P/V(parity/overflow) - флаг чётности/переполнения. Этот флаг для некоторых команд действует как флаг чётности, а для других - как флаг переполнения. Флаг выступает в роли указателя чётности при логических операциях и устанавливается в том случае, если в результате установленным оказывается чётное количество битов. Переполнение говорит вам, что после выполнения арифметического действия изменился знак операнда, причём не при переходе через 0!
CY(carry) - флаг переноса. Говорит, что в итоге арифметической операции или же при сдвиге регистра (см. ниже) произошёл перенос. Например при сложении чисел 240 и 58 дожно получиться 298, но восьми разрядных регистров хватает только на диапазон [0; 255], поэтому реально мы получим 42, а сташий девятый бит перейдёт во флаг C.
S(sign) - флак знака. Он устанавливается, если при выполнении арифметической или логической операции получился отрицательный результат.
N(negative) и H(half-carry) - используются внутри процессора при проведении двоично-десятичной коррекции при работе с BCD-арифметикой.
Надо сказать, что далеко не все команды микропроцессора оказывают какое-то влияние на флаги, а некоторые команды изменяют лишь отдельные биты флагового регистра.

3 "Условные и безусловные переходы"

В системе команд процессора имеется не одна группа инструкций переходов, а целых две. Одна из них универсальна и позволяет переходить на любые расстояния, вторая служит для более коротких переходов на растояния, не превышающие 126-129 байт. Первый тип инструкций обозначается JP(Jump - прыгнуть), второй обозначается JR (Jump Relative - относительный переход).

Безусловные переходы:

Код: Выделить всё
JR METKA JP 12345
JR #6001 JP #89AB
JR $+10 JP METKA
При первой же встрече процессором с подобной командой он перейдёт по заданному адресу без каких-либо колебаний.

Условные переходы:
Эти команды также начинаются с JP и JR, но перед параметром - адресом перехода пишется соответствующее условие (проверка одного из флагов), при выполнении которого пограмма перейдёт к требуемому адресу. В противном случае программа просто будет работать дальше. Переход по заданному адресу выполняется:
JR C, addr ;если перенос (установлен флаг переноса CY)
JR NC, addr ;если нет переноса (флаг переноса CY сброшен)
JR Z, addr ;если ноль (установлен флаг нуля Z)
JR NZ, addr ;если не ноль (флаг нуля Z сброшен)
JP C, addr ;если перенос (установлен флаг переноса CY)
JP NC, addr ;если нет переноса (флаг переноса CY сброшен)
JP Z, addr ;если ноль (установлен флаг нуля Z)
JP NZ, addr ;если не ноль (флаг нуля Z сброшен)
JP M, addr ;если отрицательный результат (установлен флаг знака S)
JP P, addr ;если результат положительный (флаг знака сброшен)
JP PE, addr ;если чётность или переполнение (установлен флаг P/V)
JP PO, addr ;если нет чётности/переполнения (флаг P/V сброшен)
Для флагов H и N условия отсутствуют, так как они используются только в неявном виде командами коррекции двоично-десятичных чисел.
Но при большом желании можно проверить и их, делается это так:

Код: Выделить всё
PUSH AF
POP DE ;/HL/BC
BIT 1, E ;для флага N
или
BIT 4, E ;для флага H
JR NZ, addr ;переход, если включен
Хотя в своей практике я ещё никогда ими не пользовался... ... Ред: Я тоже...

Глава 3 "ВЫВОД ТЕКСТОВЫХ СООБЩЕНИЙ"
4 "Вывод через команду RST 16"

Ознакомимся с простейшим выводом текстовых сообщений при помощи команд RST, но сначала узнаем их цели.
Предусмотрены они были для быстрого и удобного вызова часто используемых подпрограмм, которые расположены в нижних областях памяти, то бишь в ПЗУ.
RST 0 - иницилизация компьютера (переход к адресу 0). После её вызова компьютер сбросится и выйдет в Бейсик.
RST 8 - вызов процедуры обработки ошибок. После её выполнения в системную переменную ERR_NR(23610) закинут код ошибки, указатель стека вытащат из переменной ERR_SP (23613/14), и с него (со стека) возьмут адрес программы обработки ошибок.Изменив адрес, хранящийся в переменной ERR_SP, можно подрубить собственные прогзы обработки ошибок бейсика (зачем?).
RST 16 - программа выводит в текущий поток символ, код которого записан в аккумулятор. Куда будет производится печать - на экран или на принтер - зависит от того, какой поток открыт в данный момент. Прогза, устанавливающая текущим поток, номер которого указан в аккумуляторе, расположена по адресу 5633.
поток 0 и 1 - вывод на служебный экран.
поток 2 - вывод на основной экран.
поток 3 - вывод на принтер.
RST 24 - программа выполняет при работе интерпретатора прием очередного символа, на который указывает системная переменная CH_ADD(23645/46), и производит его проверку на принадлежность к печатным.
RST 32 - процедура выполняет последовательный просмотр символов вплоть до конца Бейсика.
RST 40 - инициализирует встроеный медленный калькулятор компьютера. О нём я здесь писать не буду, уж больно он медленный. Но если AlCo пустит слезу, то, может быть, уроке эдак в двадцатом я о нем расскажу.
RST 48 - процедура служит для создания дополнительных ячеек памяти калькулятора. на каждую ячейку выделяется по пять байт. Перед вызовом RST 48 в BC должно находиться суммарное количество байтов, которое нужно выделить для памяти калькулятора. После выполнения RST 48 в DE будет адрес начала выделенной области.
RST 56 - процедура обработки прерывания. Процедура выполняет две задачи: опрос клавки и изменение текущего значения таймера в переменной FRAMES (23672/73/74). Код последней нажатой клавиши заносится в переменную LAST_K (23560). Если нажата новая клавиша или пришло время автоповтора старой, в 5-й бит переменной FLAGS (23611) записывается единица.
Кстати, команды RST NN можно заменить на команды CALL NN. Результат будет тем же, но CALL занимает 3 байта и дольше работает.

Ну, приступим, собственно, к выводу текстовых сообщений. Как вы уже узнали, для использования команды RST 16, нужно открыть поток для вывода на основной экран, т.е. в аккумулятор занести двойку (отличники могут заносить другую цифру, но т.к. комп не может угадать, куда вам нужно кинуть сообщение (в какие координаты), для этого были задуманы управляющие и цветовые коды. Приведу только те, которые нам понадобятся:
код #16, X, Y - AT X, Y (аналог Бейсика
код #10, N - INK N, где N - это цвет (0-7)
код #11, N - PAPER N
Текст и эти данные мы будем вводить через директиву DEFB (она же DB).
Попробуем же напечатать текстовое сообщение:

Код: Выделить всё
LD A, 2 ;код потока
CALL 5633 ;открываем поток
LD HL, TXT ;HL=адрес текста
LD B, END-TXT ;длина текста
PT LD A, (HL) ;берём код
RST 16 ;и выводим
INC HL ;следующий код
DJNZ PT ;повторяем, пока не кончится
RET
TXT DB #16, 10, 5, #10, 6, #11, 1, "TEXT"
END
Этот способ не совсем оптимален, главный его недостаток - строгое ограничение текста в 256 байт.
Чтобы избавиться от этого недостатка, нужно взять один из неиспользуемых кодов (часто это 255, 128 или 0). Он будет у нас маркером конца текста, и потому должен распологаться в его конце.
В самой процедуре мы организуем проверку каждого кода на предмет маркера, и, когда он будет найден, печать остановится.

Код: Выделить всё
LD A, 2
CALL 5633
LD HL, TEXT
L0 LD A, (HL)
CP 128 ;проверка на маркер конца текста
RET Z ;если это он, то выход
RST 16
INC HL
JP L0
TEXT DB #16, 10, 5, #10, 6, #11, 1, "TEXT", 128
0
Ушел с форума
Автор FAQ
 Аватар для Mikl___
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,769
15.02.2011, 10:33
n971030, многа букаф, что сказать-то хотел?
Достаточно было дать ссылку, что взято отсюда "Из журнала ZX-Guide №1. 1998 год. Краткий урок ассемблера для ламеров (C) Alone Coder" а гуглить и читать я и сам умею...
0
188 / 120 / 4
Регистрация: 23.01.2010
Сообщений: 1,320
05.04.2011, 00:48  [ТС]
Цитата Сообщение от n971030 Посмотреть сообщение
start:
start:
Вот мы и добрались до нашей первой метки. Метки в exe-файл не идут. Первая метка начинает код программы. Можно написать хоть "tuki_puki:", лишь бы в конце кода было "end tuki_puki". Что и сообщит MASM'у, где кончилась программа, а самое главное - где она началась.

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

Добавлено через 21 минуту
сервис DOS Это прерывание служит главным входом большинства функций DOS.

Программа, запрашивающая сервис DOS, должна подготовить всю необходимую информацию в регистрах и управляющих блоках, указать в регистре AH номер желаемой функции DOS и затем вызвать прерывание INT 21H.


http://www.codenet.ru/progr/dos/int_0026.php

Добавлено через 27 минут
Сначала краткое введение в этот туториал. Win32asm не очень популярный язык программирования, и есть только несколько (хороших) туториалов. Большинство туториалов сосредотачивается на программировании win32 (т.е. Win API, использование стандартных windows методов), а не программирование на самом ассемблере, используя коды операций, регистры и т.д. Хотя Вы можете найти это и в других туториалах, они обычно объясняют программирование под DOS. Они, конечно, помогут вам изучить ассемблер, но для программирования под windows, вам не нужно знать о DOS прерываниях и о функциях ввода\вывода в порты. В windows, есть функции Win API, которые вы можете использовать в своих программах, но об этом позже. Цель этого туториала состоит в том, чтобы объяснить, как программировать на ассемблере под win32.

1.0 - Ассемблер

Ассемблер создан как замена двоичному коду, который понимает процессор. Давным-давно, когда еще не было никаких языков программирования высокого уровня, программы создавались на ассемблере. Коды ассемблера представляют непосредственно команды процессора, которые он может выполнять. Для примера:

add eax, edx

Эта инструкция, add, складывает вместе два значения. Eax и edx называются регистрами, они могут содержать значения, которые хранятся внутри процессора. Этот код будет преобразован в 66 03 C2 (шестнадцатиричный код). Процессор читает эти коды, и выполняет операцию, которую они представляют. Языки высокого уровня, например С, при компиляции преобразовывается в ассемблер, а ассемблер в двоичный код:

код C >>Компилятор>> Ассемблер >>Ассемблер>> выходной код (шестнадцатиричный)
a = a + b; add eax, edx 66 03 C2

(Учтите, что ассемблерный код упрощен, выходной код будет зависеть от контекста С кода)

1.1 - Почему?

Зачем нам использовать ассемблер, а не C и что-нибудь другое, если писать на ассемблере сложнее. Программы написаные на ассемблере быстрые и имеют очень маленькие размеры. В языках программирования высокого уровня компилятору сложнее производить выходной код. Компилятор должен выяснить метод оптимизации (по скорости или по размеру), для производства ассемблерного кода, и несмотря на то, что компиляторы постоянно улучшаются, они программируют код самостоятельно (с опцией оптимизации кода) стараясь производить как можно меньший и более быстрый код (но у них это не очень хорошо получается).


Примечание от переводчика:
Я провел эксперимент, написал программу (обычное окно с одной кнопкой в центре, которая закрывает его) на разных языках высокого уровня и после компиляции получил вот такие размеры этой самой программы:
C++ Builder 4 - 22 kb
Delphi 5 - 291 kb
Delphi 5 + библиотека KOL - 26 kb
Ассемблер MASM - около 3 kb
Так, что смотрите и делайте выводы, что лучше использовать.
Есть другое различие с некоторыми языками высокого уровня, это использование runtime DLL библиотек для их функций. Например, Visual C++ имеет библиотеку msvcrt.dll которая содержит стандартные С функции. В большинстве случаев, это работает хорошо, но иногда возникают проблемы с версиями dll. У пользователя всегда должны быть установленны эти DLL-библиотеки (что не всегда бывает). Для Visual C это не проблема, они устанавливаются вместе с windows.
Visual Basic даже не преобразовывает свой язык в ассемблер (хотя версия 5 и выше делают это частично, но не полностью), это сильно зависит от msvbvm50.dll, виртуальной машины Visual Basic. Exe файл, который создан VB состоит из простых частей кода и многих вызовов этой DLL. Вот почему VB очень медленный. Ассемблер это и есть самый быстрый язык. Он использует только системные DLL: kernel32.dll, user32.dll, и т.д.


Другое непонимание в том, что многие люди думают, что на ассемблере невозможно программировать. Безусловно, это сложно, но очень даже возможно. Создавать большие проекты на ассемблере, это довольно сложно, я использую его для создания маленьких программ, DLL библиотек и частей кода, где требуется скорость. Также, есть большое различие между DOS и Windows программами. DOS программы мспользуют прерывание как 'функции'. Подобно int 10 для видео, int 13 для доступа к файлам и т.д. В win, есть API, приложения программирующие интерфейс. Этот интерфейс состоит из функций, которые вы можете использовать в своих программах. В DOS программах, прерывания имеют номер прерывания и номер функции. В Win, API функции имеют только имена (например: MessageBox, CreateWindowEx). Вы можете импортировать библиотеки (DLL) и использовать функции внутри них. Это облегчает программирование на ассемблере. Подробнее об этом в следующих уроках.

2.0 - Начало

Достаточно введения, давайте начнем. Чтобы программировать на ассемблере, вам будут нужны некоторые инструменты. Ниже вы увидете, какие инструменты я буду использовать в этом учебнике. Я советую вам установить те же самые инструменты, чтобы вы могли следовать учебнику и пробовать примеры. Я также дал некоторые вырианты, для большинства инструментальных средств, вы можете выбрать вариант для этого учебника, но предупреждаю, что между ассемблерами (masm, tasm и nasm) имееются большие различия. В этом учебнике будет использоваться MASM, благодаря его полезным функциям (таким как invoke и т.д.), которые намного упрощают программирование. Конечно вы свободно можете использовать любой ассемблер, который предпочитаете, но будет тяжелее следовать этому учебнику и вам нужно будет преобразовывать примеры, чтобы они работали с вашим ассемблером.

Ассемблер
Использованный: Masm (из пакета win32asm )
Расположение: Win32asm.cjb.net
Описание: Конвертирует исходный текст ассемблера (опкоды) в объектный файл для процессора.
Описание: Masm, макроассемблер, является ассемблером с несколькими полезными особенностями, подобно 'invoke', которые облегчают вызовы функций API и проверяет типы данных, вы поимете это позже в этом учебнике. Если вы прочитали текст выше, то знаете, что в этом учебнике используют MASM.

Выбор:
Tasm [dl], nasm [dl]


Линкер
Использованный: Microsoft Incremental Linker (link.exe)
Расположение: Win32asm.cjb.net (in the win32asm package)
Описание: компоновщик 'связывает' все объектные файлы и библиотеки (для импорта DLL) вместе, чтобы произвести конечную выполнимую программу.
Описание: я буду использовать link.exe, который является доступным в пакете win32asm на странице Iczelion'а, но можно использовать и другие.

Выбор:
Tasm linker [dl]


Редактор ресурсов
Использованный: Borland Resource Workshop
Расположение: www.crackstore.com
Описание: редактор ресурсов используется для создания ресурсов (изображения, диалоги, точечные рисунки, меню).
Описание: Подойдет большинство редакторов, лично я предпочитаю Borland Resource Workshop, но вы можете использовать то, что хотите. Учтите: файлы ресурса, созданные с Resource Workshop иногда вызывают проблемы с компилированием ресурса, если Вы хотите использовать этот редактор, Вы также должны загрузить tasm, который содержит brc32.exe для компилирования ресурсов стиля Borland.

Выбор:
Symantec Resource Editor, Resource Builder, и многие другие


Текстовый редактор
Используемый: Ultraedit
Расположение: www.ultraedit.com
Описание: Текстовый редактор нуждается в описании?
О: Выбор текстового редактора это кому как, лично мне очень нравится Ultraedit. Вы можете скачать мой wordfile для ultraedit, тогда вы получите подсветку синтаксиса ассемблера. По крайней мере выберите текстовый редактор с подсветкой синтаксиса (ключевые слова будут автоматически окрашены), это очень полезная функция, делает ваш код более легким для чтения и записи. Ultraedit также имеет список функций, для быстрой вставки в ваш код. [download wordfile here]

Выбор:
Один из миллионов текстовых редакторов [здесь]


References
Используемый:Справочник програмиста "Win32 Programmer's reference"
Расположение: www.crackstore.com (или поищите в интернете)
Описание: Вам нужны будут некоторые справки по функциям Win API. Наиболее нужный справочник программиста "win32 programmer's reference" (win32.hlp). Это большой файл, около 24 mb (некоторые версии всего 12 mb но не полные). В этом файле описаны все функции системных DLL (kernel, user, gdi, shell и т.д.). По крайней мере вы будете нуждаться в этом файле, другие справочники (sock2.hlp, mmedia.hlp, ole.hlp и т.д.) также полезны, но не необходимы.


От переводчика: Эти файлы включаются в стандартные пакеты типа Borland C++ Builder, Delphi и т.д.

Выбор:
нет


2.1 - Установка инструментальных средств

Теперь у вас есть эти инструменты, устанавливаете их где-нибудь. Вот несколько важных замечаний:

Установите пакет masm на том же диске, на котором хотите писать ваши исходные файлы ассемблера. Это гарантирует то, что пути к файлам вложения и библиотекам будут правильными.
Добавьте каталог bin masm'а (или tasm'а) к вашему пути в autoexec.bat и перезагрузитесь.
Если у вас есть Ultraedit, используте wordfile который можете скачать выше и включите просмотр списка функций.
2.2 - Папка для ваших исходников

Создайте папку "win32" (или с другим именем) где-нибудь (на том же диске, что и masm), и создайте подпапку для каждого проекта, который вы делаете.

3.0 - Основы ассемблера

Эти туториалы обучат вас основам ассемблера.

3.1 - Коды операции (далее опкоды)

Программы Ассемблера созданы с помощью опкодов. Опкоды это команды, которые понимает процессор. Например:

ADD

Инструкция add складывает вместе два числа. Большинство опкодов имеют операнды:

ADD eax, edx

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

3.2 - Регистры

Есть несколько размеров регистров: 8 бит, 16 бит, 32 бит (и больше на MMX процессорах). В 16-разрядных программах, вы можете использовать только 8 и 16 битные регистры. В 32-разрядных программах вы также можете использовать 32 битные регистры.
Некоторые регистры являются частью других; например, если EAX содержит значение EA7823BBh, вот то, что содержат другие регистры.

EAX EA 78 23 BB
AX EA 78 23 BB
AH EA 78 23 BB
AL EA 78 23 BB

регистры ax, ah, al - части регистра eax. Eax это 32-битный регистр (доступный только начиная с 386+), ax содержит младшие 16 бит (2 байта) регистра eax, ah содержит старший байт регистра ax, и al содержит младший байт регистра ax. Регистр ax - 16 битный, al и ah - 8 битные. Так из примера выше, вот значения регистров:

eax = EA7823BB (32-бит)
ax = 23BB (16-бит)
ah = 23 (8-бит)
al = BB (8-бит)

Пример использования регистров (не заботьтесь об опкодах, просто смотрите на регистры и описание):

mov eax, 12345678h mov загружает значение в регистр (Обратите внимание: 12345678h это шестнадцатиричное число, т.к. в конце стоит суффикс 'h')
mov cl, ah копирует старший байт регистра ax (67h) в регистр cl
sub cl, 10 вычесть 10 (десятичное) из значения в регистре cl
mov al, cl и сохранить его в младшем байте регистра eax.

Давайте исследуем вышеприведенный код:
Mov команда может перемещать значение от регистра, памяти или непосредственного значения к другому регистру. В примере выше, eax содержит 12345678h. Затем значение регистра ах (3-ий байт слева в регистре eax) копируется в регистр cl (самый младший байт регистра ecx). Далее, из регистра cl вычитается 10, и затем значение из регистра cl копируется в регистр al(самый младший байт регистра eax).

Есть различные типы регистров:

Универсальные

Эти 32-битные (и 16/8 для их компонентов) регистры могут использоваться для чего угодно:

eax (ax/ah/al) Аккумулятор
ebx (bx/bh/bl) Базовый регистр
ecx (cx/ch/cl) регистр-счетчик
edx (dx/dh/dl) регистр данных

Хотя они и имеют названия, вы можете использовать их как угодно.

Сегментные регистры

Сегментные регистры определяют сегмент памяти, которая используется. Вероятнее всего, они вам не понадобятся в win32asm, потому, что windows использует плоскую систему памяти. В dos, память разделена на сегменты по 64kb, так, что если вы хотите определить адрес памяти, вы определяете сегмент и смещение (например 0172:0500 (сегмент:смещение)). В windows, сегменты имеют размер 4Gb, так, что в сегментации в win. Сегментные регистры всегда - 16-битные.

CS Сегмент кода
DS Сегмент данных
SS Сегмент стека
ES Дополнительный сегмент
FS (только с 286+) Универсальный сегмент
GS (только с 386+) Универсальный сегмент

Регистры указателя

Фактически, вы можете использовать регистры указателя, как универсальные регистры (eip - исключение), пока вы сохраняете их первоначальные значения. Регистры указателя называются так потому, что их часто используют для сохранения адресов памяти. Некоторые опкоды (movb,scasb, и т.д.) также их используют.

esi (si) Индекс источника
edi (di) Индекс приемника
eip (ip) Указатель команды

Регистр EIP (или IP в 16-разрядных программах) содержит указатель на команду, которую собирается выполнить процессор. Так что вы не можете использовать регистр eip как универсальный.

Регистры указателя стека

Есть 2 стековых регистра: esp & ebp. Esp содержит текущую позицию стека в памяти (подробнее об этом в следующих уроках). Ebp используется в функциях как указатель на локальные переменные.

esp (sp) Указатель стека
ebp (bp) Указатель базы кадра стека
0
Ушел с форума
Автор FAQ
 Аватар для Mikl___
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,769
05.04.2011, 13:18
Автор, что сказать-то хотел? 4 страницы надерганных отовсюду цитат, на статью не тянет, на учебник тем более...
0
0 / 0 / 0
Регистрация: 01.04.2014
Сообщений: 11
10.11.2014, 18:44
помогите пожалуйста разобраться с командой LEA, я не могу понять одну вещь, по описанию данная команда возвращает в приемник эффективный адрес источника, то есть я так понял что команда lea eax,[My_unit] вернет в eax смещение My_unit смещение относительно начала сегмента где находится значение этой переменной, но если в качестве источника используется другой регистр то в регистр приемник возвращается значение регистра источника?
0
Ушел с форума
Автор FAQ
 Аватар для Mikl___
16377 / 7689 / 1080
Регистрация: 11.11.2010
Сообщений: 13,769
11.11.2014, 03:58
Цитата Сообщение от pshak Посмотреть сообщение
но если в качестве источника используется другой регистр то в регистр приемник возвращается значение регистра источника?
lea eax,[ebx] эквивалентно mov eax,ebx
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.11.2014, 03:58

Direct Editor - наш ответ Яндекс Директ.Коммандеру и Google AdWords.Editor-у
Компания &lt;b&gt;PromoSoft&lt;/b&gt; сообщает о выходе альфа-версии десктопного программного продукта &lt;b&gt;Direct Editor&lt;/b&gt;, центра...

Подскажите пожалуйста хорошую литературу для изучения с++, для новичков
Чтобы подошла человеку , который не сталкивался с программированием , а вот сейчас ему очень срочно и быстро нужно освоить хотя бы главные...

Не для новичков по C#
Задания не для новичка уж явно.., не могу сделать эти первые три задания? Ну вот 4-ую сделал, там я думаю любой сделает, даже без...

IT для новичков
Здравствуйте, вопрос такой: какие IT навыки, помимо знания языков программирования, могут понадобится в работе. Ну там слепой набор... И...

Скрипт для Editor
Здравствуйте! Для игры нужно делать траекторию движения по точкам. Создавать в ручную массив из точек накладно выходит. Как сделать так,...


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

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Новые блоги и статьи
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru