gc986 wrote:
1) Я повесил обновление времени на обработчик нажатия на кнопку, чтобы сделать время постоянно обновляющимся необходимо создать вечный цикл?
совершенно верно что нужен вечный цикл - но его не нужно создавать, он уже есть! Этот вопрос я рассмотрю разом с этим:
gc986 wrote:
6) Не совсем понимаю как работает главный цикл программы
Code: Select all
wait_event:
mcall 10
dec eax
jz redraw
dec eax
jz key
cmp eax,3
jz button_event
Постоянно происходит вызов системной функции 10, и дальше перебор вариантов действий. Как система узнаёт что произошло событие обновления экрана, а не нажатия на кнопку например?
Давайте посмотрим как он работает. Из описания системной функции 10
http://wiki.kolibrios.org/wiki/SysFn10/ru мы знаем как она работает: при вызове выполнение программы приостанавливается, покуда не произойдёт событие, связанное с программой. Как только событие происходит, система "отпускает" программу и она продолжает выполнение, с одним изменением - в регистр eax записывается код произошедшего события. То есть, например, если нажата кнопка, в eax будет число 3. Вот мы и сравниваем значение eax с разными константами, если в eax единица например - перерисовываем окно, и после возвращаемся обратно к ожиданию события. Как система узнаёт что за событие - нам не важно, нам важно только как об этом узнаёт программа, ну вот я и описал вроде) надеюсь правильно понял вопрос.
Теперь что касается первого вопроса, про бесконечный цикл. Главный цикл программы уже является бесконечным циклом, в который мы можем как раз добавить вызов процедуры обновления времени. Посмотрим что нам нужно сделать для обновления: во-первых, пересчитать строку времени, во-вторых - перерисовать окно (на самом деле как-то возможно частичное обновление окна, но я так ни разу не делал, боюсь обмануть). И это надо делать периодически (или чаще). Один из вариантов как этого можно добиться (далеко не самый правильный вариант - но должно по крайней мере работать) следующий:
Code: Select all
wait_event:
; вместо сисфункции 10 применим http://wiki.kolibrios.org/wiki/SysFn23/ru
;работает как 10я за одним исключением, после 0.5 секунд (в данном случае)
;отпускает программу, записывая в eax значение 0.
mcall 23, 50
; dec для сравнения с нулём не годится, используем cmp
cmp eax, 0
; тут я предполагаю что процедура обновления времени называется update_time
;и заканчивается командой jmp redraw
jz update_time
dec eax
jz redraw
dec eax
jz key
cmp eax,3
jz button_event
Ну вроде как-то так, теперь если программу не "вешать" постоянным вызовом событий (например, зажиманием кнопки клавиатуры) - время должно обновляться
gc986 wrote:2) В учебнике написано что and - оператор логического умножения. Не могли бы вы по подробнее написать зачем и как используется эта команда?
конечно могу. Тем более что для этого мне нужно всего лишь скопировать практически готовый ответ из этого самого учебника:
Применение:
Команда and используется для логического умножения двух операндов. Результат операции помещается по адресу первого операнда. Эту команду удобно использовать для принудительной установки или сброса определенных битов операнда.
Например, преобразуем двузначное упакованное BCD-число в его символьный эквивалент.
дальше идёт кстати код, который (примерно) я изобретал в предыдущем ответе
там чуть меньше комментариев правда, может мне учебник написать
В общем, у нас тут как раз применение для принудительного сброса определённых битов. Вот есть bl, в нём допустим значение 0x23 (это значит 23 часа пускай). Нам нужно получить символ '3' (оставим пока в покое десятки). Для этого нужно удалить 0x20 из 0x23. Как же это сделать? Можно вычесть 0x20 из 0x23. Но программа ведь не знает что там именно два десятка часов! Поэтому воспользуемся логическими операциями, например and. Что она делает? Для каждого бита операндов выполняет следующее: если у обоих операндов текущий бит равен 1, то вернуть 1, иначе вернуть 0. Возвращает в первый операнд. Как это можно использовать? Посмотрим на наше число 0x23 в бинарном виде: 0b00100011. Что будет если мы съandим его с, например, 0b00001111 (0x0f)? Совершенно верно, там где у второго операнда 0 - у результата будет 0, а где 1 - там результат будет такой же, как в первом операнде! Значит получим 0b00000011, а это число 0x03 или просто 3! Как удачно подвернулся следующий вопрос:
gc986 wrote:3) Зачем складывать с '0', ведь число +0 это то же самое число или здесь другая логика?
Давайте продолжим мучать наш bl, который содержит уже 0x03, или 3. Если вы запишете это значение в какую-нибудь строку, выводящуюся потом на экран (попробуйте!), вы увидите вместо символа '3' что-то другое. Что именно - давайте посмотрим вместе вот тут
https://ru.wikipedia.org/wiki/ASCII - упс, похоже это вообще какой-то служебный символ, и я полагаю на выводе будет пробел или кракозябра какая. Что же делать, как же быть, как нам тройку выводить... А посмотрим на таблицу снова, и найдём там символ тройки - вот же он, с кодом 0x33. То есть чтобы вывести символ '3' надо к числу 0x03 добавить число 0x30. Но я не очень люблю магические числа, где гарантия что через лет пять вы вспомните что это за число такое? Потому то я и прибавляю к нашему bl
код символа '0' (видите, он в кавычках - значит это именно код символа, равный 0x30, а не число 0!), очевидно для 0x03 мы получим тогда 0x33, то есть '3'.
gc986 wrote:
4) Каждый символ в строке занимает 1 байт? (никогда не обращал на это внимание при программировании на языках высокого уровня)
ага, 1 байт в кодировке которая используется в Колибри. Бывают и другие кодировки - двубайтовые, четырёхбайтовые, и даже с переменным количеством байт. Но для вывода в Колибри именно однобайтовая кодировка обычно применяется. Первая половина кодовой таблицы - уже знакомая нам ASCII, вторая - национальные и дополнительные символы. Кстати, поделитесь - с какими языками высокого уровня вы знакомы? Зная это, мне проще будет показывать на конкретных примерах всякое.
ну я вот на него сослался, значит на что-то он годится
А если серьёзно, можно использовать любой учебник, только смотрите чтобы там был описан ассемблер для x86. Отличаться у разных ассемблеров будет синтаксис, например насколько я помню квадратные скобочки чуть ли не только в FASM применяются, в других ассемблерах иначе задаётся то что работа идёт со значением а не с адресом. То есть команды такие же, только несколько иначе записываются и всё.