Page 38 of 77

Re: Помогите новичку

Posted: Sat Aug 11, 2012 10:08 am
by Akyltist
исходный код с подсветкой http://pastie.org/4454257

Code: Select all

  use32
  org	 0x0

  db	 'MENUET01'
  dd	 0x01
  dd	 START
  dd	 I_END
  dd	 0x1000
  dd	 0x1000
  dd	 0x0
  dd	 0x0

include 'lang.inc'
include 'macros.inc'

START:
red:
    call draw_window
still:
    mcall 10            ; функция 10 - ждать события
    cmp  eax,1          ; перерисовать окно ?
    je   red            ; если да - на метку red
    cmp  eax,2          ; нажата клавиша ?
    je   key            ; если да - на key
    cmp  eax,3          ; нажата кнопка ?
    je   button         ; если да - на button
    jmp  still          ; если другое событие - в начало цикла
;end_still

key:                    ; нажата клавиша на клавиатуре
    mcall 2             ; функция 2 - считать код символа (в ah) (тут в принципе не нужна)
    mov [codes],1       ; Если нажали любую клавишу то меняем значение на 1
    jmp  still          ; вернуться к началу цикла
;end_key

button:
    mcall 17            ; 17 - получить идентификатор нажатой кнопки
    cmp   ah, 1         ; если НЕ нажата кнопка с номером 1,
    jnz   still 	      ; вернуться
    mcall -1            ; иначе конец программы
;end_button

draw_window:
    mcall 12, 1         ; функция 12: отрисовка окна; 1 - начинаем рисовать

    mcall 0, <200,200>, <200,50>, 0x33AABBCC,,title
    cmp  [codes],1      ; сравниваем
    jne   exit          ; если не равно то на выход, иначе ... выводим месадж

    mcall 4, <3, 8>, 0, message, message.size
exit:
    mcall 12, 2         ; функция 12: отрисовка окна; 2, закончили рисовать
    ret                 ; выходим из процедуры на мессто откуда вызвали


;---------------------------------------------------------------------
;---  ДАННЫЕ ПРОГРАММЫ  ----------------------------------------------
;---------------------------------------------------------------------
  codes dd 0

lsz message,\
  ru,'Нажмите любую клавишу...',\
  en,'Press any key...',\
  fr,'Pressez une touche...'

lsz title,\
  ru,'ПРИМЕР ПРОГРАММЫ',\
  en,'EXAMPLE APPLICATION',\
  fr,"L'exemplaire programme"

;---------------------------------------------------------------------

I_END:                  ; метка конца программы
Суть в том, что при нажатии любой клавиши переменной codes dd 0 присваивается значение равное 1, а в цикле отрисовки, если это значение равно 1, то следует выводить message. Но message становится видно, только если нажать клавишу, а потом что либо сделать с окном, то есть вызвать перерисовку. В принципе понятно, зачем что либо перерисовывать, если ничего не изменилось. Вопрос в том, как принудительно вызвать перерисовку. будет ли логичным вставить call draw_window или jmp red после mov [codes],1 (строка из обработки нажатия клавиш - метка key)????

Re: Помогите новичку

Posted: Sat Aug 11, 2012 12:24 pm
by IgorA
Akyltist wrote:Вопрос в том, как принудительно вызвать перерисовку. будет ли логичным вставить call draw_window или jmp red после mov [codes],1
Можно вызывать полную перерисовку окна через call draw_window. Но чтобы не было миганий при перерисовке окна лучше вынеси вывод текста

Code: Select all

mcall 4, <3, 8>, 0, message, message.size
в отдельную функцию, которую вызывай из draw_window и при необходимости из других функций.
Функции mcall 12, 1 и mcall 12, 2 связанны с созданием/удалением кнопок, потому вызывать их при небольших обновлениях окна не обязательно.

Re: Помогите новичку

Posted: Sat Aug 11, 2012 12:54 pm
by Akyltist
Можно вызывать полную перерисовку окна через call draw_window. Но чтобы не было миганий при перерисовке окна лучше вынеси вывод текста
в отдельную функцию, которую вызывай из draw_window и при необходимости из других функций.
Функции mcall 12, 1 и mcall 12, 2 связанны с созданием/удалением кнопок, потому вызывать их при небольших обновлениях окна не обязательно.
Спасибо, помогло избавится от мерцания, просто в начале также как вы описали сделал , вынес функцию, но почему то программа закрывалась. Поэтому сделал так как выше, но появилось мерцание, что и навело на эти вопросы. Потом разобрался что надо было использовать jmp а не ret и всё стало работать корректно. Большое спасибо, многое встало на свои места.

PS: скачал e-zine - очень полезный журнал.... особенно первый выпуск....

Re: Помогите новичку

Posted: Sat Aug 11, 2012 4:59 pm
by Akyltist
Пытаюсь освоить конкатенацию строк

Code: Select all

	mov edi, text
	xor al, al 
	cld 
	rep scasb				;вот собственно и получил конец первой строки, теперь
	add edi, [codes]				; её длина
	mov esi, text2 
	mov ecx, [codes2]
	rep movsb
;--- Где...
	codes  dd 0
	codes2 dd 0
	text db 'Bye World! KOS!'
	text2 db 'My String!'
Вот результат:
Image
Длина строк text и text2 до слияния определяются автоматически при помощи функции strlen (самописная) правильно. После сложения, длина text тоже правильная (см скриншот). Но при повторном нажатии на клавишу, ничего не происходит, то есть строка text не увеличивается второй раз на длину строки text2. Но если убрать часть кода:

Code: Select all

	mov edi, text
	add edi, [codes]				; её длина
	mov esi, text2 
	mov ecx, [codes2]
	rep movsb
;--- Где...
	codes  dd 0
	codes2 dd 0
	text db 'Bye World! KOS!'
	text2 db 'My String!'
То text увеличивается сколько угодно раз при нажатии кнопки, но при этом вторая строка увеличивается сама на себя)) Следовательно при втором нажатии она к первой добавляет не My String! , а My String!My String!

помогите разобраться с данным казусом, а то я уже что-то перешёл на метод слепого котёнка Шрёдингера в абсолютно тёмном мешке, объём которого равен = сферической функции расширения яйца цыплёнка, в вакууме.

PS: полный код http://pastie.org/4455488

Re: Помогите новичку

Posted: Sun Aug 12, 2012 10:16 am
by Albom
Akyltist
1. Строки лучше использовать в стиле Си (завершающиеся нулевым символом):
text db 'Bye World! KOS!', 0
text2 db 'My String!', 0
2. Для конкатенации необходимо место, куда собственно будет записываться результат (либо в исходную строку). В любом случае в строку
text db 'Bye World! KOS!'
записывать больше, чем байт в ней, ничего не получится - всё, что находится дальше, просто затрётся.
3. Сбрасывать флаг направления (cld) каждый раз не нужно (если в программе не используется std). Да и по умолчанию он уже сброшен.
4. Функцию, вычисляющую длину строки, можно реализовать проще (у меня где-то была моя реализация - могу посмотреть и выложить).

Re: Помогите новичку

Posted: Sun Aug 12, 2012 12:28 pm
by Akyltist
Спасибо, за ответ
Собственно со строками вчера разобрались и по поводу cld тоже в irc объяснили
На реализацию с удовольствием посмотрю, для меня полезно будет. (пока использую реализацию применяемую в ядре Колибри)

Re: Помогите новичку

Posted: Sun Aug 12, 2012 2:23 pm
by Albom
Оказалось, что моя функция реализована значительно хуже, чем в ядре. Тем не менее, так как её нашёл, выкладываю:

Code: Select all

	mov ebx, 256
	mov ecx, ebx
	mov edi, message
	xor al, al
@@:
	dec ecx
	scasb
	jne @b

	sub ecx, ebx
	neg ecx
	dec ecx

Re: Помогите новичку

Posted: Sun Aug 12, 2012 11:59 pm
by Serge

Re: Помогите новичку

Posted: Fri Aug 17, 2012 8:30 pm
by Nable
Мало того что в AT&T синтаксисе, так ещё и > 1994 > 2012 .
Это печально, очень печально.

Re: Помогите новичку

Posted: Fri Aug 17, 2012 8:48 pm
by Artyom
Nable wrote:Мало того что в AT&T синтаксисе, так ещё и > 1994 > 2012 .
Это печально, очень печально.
У них читается с права НА ЛЕВО :)
1994 < 2012 < 0 :)

Re: Помогите новичку

Posted: Mon Aug 20, 2012 9:12 pm
by Akyltist

Code: Select all

    xor eax, eax
    mov eax,12
    finit
    fld  dword [cel]  ; ST0 = [cel]
    fdiv dword [eax] ; ST0 = ST0 / 12
    fstp dword [cel] ; [cel] = ST0 и вытолкнуть ST0
;   вывод в окно
;-----

    cel   dd -232456.456784356345
вывожу в окно cel и вижу -232456.456784356345

Вопрос! Почему,мой больной мозг думает, что оно, должно было поделить cel на 12 ?

Re: Помогите новичку

Posted: Mon Aug 20, 2012 9:49 pm
by Serge

Code: Select all

    xor eax, eax - лишняя команда
    mov eax,12
    finit - лишняя команда
    fdiv dword [eax] ; ST0 = ST0 / 12
Делим ST0 на float по адресу 0012

Меняем на

Code: Select all

    fld  dword [cel]  ; ST0 = [cel]
    fidiv dword [_12] ; ST0 = ST0 / 12
    fstp dword [cel] ; [cel] = ST0 и вытолкнуть ST0
    ...
    ...
    ...
_12 dd 12

Re: Помогите новичку

Posted: Tue Aug 21, 2012 11:25 am
by Akyltist
Благодарю Serge.

Еще вопрос, fidiv - это целочисленное деление, а мне надо именно деление чисел с плавающей запятой, я так понимаю fdiv но возникает вопрос, куда записывается это число и его дробная часть, не остаток а именно дробная часть? Или оно пишет его в ST0, в соответствии со стандартом IEEE754 в виде вещественного числа (с мантисой и порядком)?

Просто задача:
вещественное знаковое поделить на вещественное знаковое и получить вещественное знаковое
при чем чтобы все три участника этой операции были типа dd (не dq и не dt))) и не BCD).

PS: еще раз спасибо, пошел пока сам разбираться.

Re: Помогите новичку

Posted: Tue Aug 21, 2012 11:40 am
by Serge
если делишь на float то fdiv dword [addr], если на double fdiv qword [addr] где по addr находится делитель в вещественном формате.

Re: Помогите новичку

Posted: Tue Aug 21, 2012 12:00 pm
by Akyltist
вау, все работает - благодарю. Дело было как раз в dd - dq !!!!
пойду постигать азы дальше.

PS: как это приятно то а.... прям морфин по телу.