Задать вопрос
TalismanChet
@TalismanChet
Лицо зла

Как исправить движение мыши?

Я пишу свою ОС на ассемблере (под все платформы, сейчас - х86-16), и работал над мышкой. я использовал решение этого вопроса из стека, но курсор просто бешено носится по экрану с такой скоростью, что отследить его во время движения невозможно. Предоставить весь код проблематично, но при необходимости, возможно (займет прилично времени).

АПД:

я смог скачать исходник. Не бейте палкой, я всё в одном файле кодил.

Сам исходник
format binary

	include "lib/kernel.inc"

	org 0x7C00

	xor ax, ax
	mov ds, ax
	mov ss, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, 0xFFFE

	jmp 0:@f

@@:

	clc
	mov ah, 0x02
	mov al, 8
	mov bx, 0x1000
	mov cx, 0x0002
	int 0x13
	mov ax, 0x0013
	int 0x10
	jnc 0x1000

	cli
	hlt

draw_pixel_13:
	; cx, dx, al = x, y, c
	push es VIDEOSEG
	pop es
	mov bx, dx
	push cx
	mov cx, 319
.cycle:
	add bx, dx
	loop .cycle
	pop cx
	add bx, cx
	mov byte [es:bx], al
	pop es
	ret

draw_rect_13:
	push ds bx di
	imul bx, 320
	add bx, ax
	mov ax, VIDEOSEG
	mov ds, ax
.__:
	push si
	jmp ._
._:
	dec si
	mov [bx+si], cl
	jnz ._
	pop si
	add bx, 320
	dec di
	jnz .__
	pop di bx ds
	ret

times 510-$+$$\
	db 0x00
	dw 0xAA55

;;===    KERNEL   ===;;

	org 0x1000

kernel.routine.startup:
	call kernel.routine.mouse.init
	call kernel.routine.mouse.enable
	;invc!set 0x08, kernel.routine.timer
	;invc!set 0x21, kernel.routine.osapi

	call kernel.routine.video
	jmp kernel.routine.idle

kernel.routine.video:
	cli
	video!fill 0x4E
	video!window 30, 40, 100, 60, 0x1A, 0xFF, 13 , 0x1F
	video!cursor
	sti
	ret

kernel.routine.idle:

	cmp byte [kernel.system.render], 0
	je kernel.routine.idle.pass_render
	call kernel.routine.video
	mov byte [kernel.system.render], 0
kernel.routine.idle.pass_render:

	jmp kernel.routine.idle

kernel.routine.mouse.init:
	push es bx
	int 0x11
	test ax, 4
	jz kernel.routine.mouse.init.error
	mov ax, 0xC203
	mov bh, MOUSE_RESOLUTION
	int 0x15
	jc kernel.routine.mouse.init.error

	push cs
	pop es

	mov bx, kernel.routine.mouse.dummy
	mov ax, 0xC207
	int 0x15
	jc kernel.routine.mouse.init.error

	clc
	jmp kernel.routine.mouse.init.finish
kernel.routine.mouse.init.error:
	stc
kernel.routine.mouse.init.finish:
	pop bx es
	ret

kernel.routine.mouse.enable:
	push es bx
	call kernel.routine.mouse.disable

	push cs
	pop es
	mov bx, kernel.routine.mouse.callback
	mov ax, 0xC207
	int 0x15

	mov ax, 0xC200
	mov bh, 1
	int 0x15

	pop bx es
	ret

kernel.routine.mouse.disable:
	push es bx

	mov ax, 0xC200
	xor bx, bx
	int 0x15

	pop bx es
	ret

kernel.routine.mouse.callback:
	push bp
	mov bp, sp
	push ds ax bx cx dx cs
	pop ds

	mov al, [bp+12]
	mov bl, al
	mov cl, 3
	shl al, cl

	sbb dh, dh
	cbw
	mov dl, [bp+8]
	mov al, [bp+10]

	neg dx
	mov cx, [kernel.shared.cursor.ypos]
	add dx, cx
	mov cx, [kernel.shared.cursor.xpos]
	add ax, cx

	mov byte [kernel.shared.cursor.stat], bl
	mov word [kernel.shared.cursor.xpos], ax
	mov word [kernel.shared.cursor.ypos], dx
	not byte [kernel.system.render]

	pop dx cx bx ax ds bp

kernel.routine.mouse.dummy:
	retf

kernel.shared.osmeta.name db "HexOS", 0x00
kernel.shared.cursor.stat db 0
kernel.shared.cursor.xpos dw 300
kernel.shared.cursor.ypos dw 300

kernel.system.render db 0

times 4096-$+$$\
	db 0x00


Заголовок к исходнику
VIDEOSEG = 0xA000

MOUSE_RESOLUTION = 127

macro invc!set\
		vector*,\
		offset* {
	cli
	push ds bx word 0
	pop ds
	mov word bx, vector
	shl word bx, 2
	add word bx, 0
	mov word [bx], offset
	mov word [bx+2], 0
	pop bx ds
	sti
}

macro video!set_at x, y, c {
	push cx dx ax bx
	mov cx, x
	mov dx, y
	mov al, c
	call draw_pixel_13
	pop bx ax dx cx
}

macro video!rect x, y, w, h, c {
	push di si cx bx ax
	mov cl, c
	mov ax, x
	mov bx, y
	mov si, w
	mov di, h
	call draw_rect_13
	pop ax bx cx si di
}

macro video!fill c {
	video!rect 0, 0, 320, 200, c
}

macro video!smrect x, y, w, h, c {
	video!rect x, y, w, 1, c
	video!rect x, y, 1, h, c
	video!rect x, y+h, w+1, 1, c
	video!rect x+w, y, 1, h+1, c
}

macro video!srect x, y, w, h, c {
	push ax bx
	video!rect x, y, w, 1, c
	video!rect x, y, 1, h, c
	mov ax, h
	add ax, y
	inc ax
	video!rect x, ax, w, 1, c
	mov bx, w
	add bx, x
	inc bx
	video!rect bx, y, 1, h, c
	pop bx ax
}

macro video!window x, y, w, h, bg, cnt, hdh, hbg {
	video!rect x, y, w, h, bg
	video!rect x, y, w, hdh-1, hbg
	video!smrect x, y, w, h, cnt
	video!smrect x, y, w, hdh-1, cnt
	video!rect x+w-hdh, y+1, hdh, hdh-2, 0x04

	video!set_at x+w-hdh/2-1-0, y+hdh/2-0, cnt
	video!set_at x+w-hdh/2-1-1, y+hdh/2-1, cnt
	video!set_at x+w-hdh/2-1-2, y+hdh/2-2, cnt
	video!set_at x+w-hdh/2-1-1, y+hdh/2+1, cnt
	video!set_at x+w-hdh/2-1-2, y+hdh/2+2, cnt
	video!set_at x+w-hdh/2-1+1, y+hdh/2-1, cnt
	video!set_at x+w-hdh/2-1+2, y+hdh/2-2, cnt
	video!set_at x+w-hdh/2-1+1, y+hdh/2+1, cnt
	video!set_at x+w-hdh/2-1+2, y+hdh/2+2, cnt
}

macro memory!copy srcseg, srcofs, dstseg, dstofs, bufsiz {
	push cx di es si ds bufsiz dstofs dstseg srcofs srcseg
	pop ds si es di cx
	rep movsb
	pop ds si es di cx
}

macro video!flip {
	memory!copy 0xAFA0, 0x0000, 0xA000, 0x0000, 0xFA00
}

macro video!cursor {
	push ax bx

	mov ax, word [kernel.shared.cursor.xpos]
	mov bx, word [kernel.shared.cursor.ypos]

	video!set_at ax, bx, 0xFF

	inc bx
	video!set_at ax, bx, 0xFF

	inc ax
	video!set_at ax, bx, 0xFF

	inc bx
	dec ax
	video!set_at ax, bx, 0xFF

	inc ax
	video!set_at ax, bx, 0xFF

	inc ax
	video!set_at ax, bx, 0xFF

	dec ax
	inc bx
	video!set_at ax, bx, 0xFF

	dec ax
	video!set_at ax, bx, 0xFF

	inc bx
	add ax, 2
	video!set_at ax, bx, 0xFF

	pop bx ax
}


Батник для сборки и отладки:
fasm os.asm
qemu-system-i386 os.bin
  • Вопрос задан
  • 268 просмотров
Подписаться 2 Средний 11 комментариев
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
mov al, [bp+12]
  mov bl, al
  mov cl, 3
  shl al, cl

  sbb dh, dh
  cbw
  mov dl, [bp+8]
  mov al, [bp+10]

Этот кусок кода из обработчика перемещений мыши должен делать знаковое расширение 9-битных координат, но я вижу, что в существующем коде в обработчик перемещений всегда приходят нули в координатах x и y, а из-за этого знакового расширения отрицательные dx и dy всегда становятся равными -256. Если добавить вызов функции initialize (0xc205) прерывания 0x15 в mouse.init с 3-байтными пакетами:
kernel.routine.mouse.init:
  push es bx
  int 0x11
  test ax, 4
  jz kernel.routine.mouse.init.error
  mov ax, 0xC205
  mov bh, 3
  int 0x15
  jc kernel.routine.mouse.init.error
  mov ax, 0xC203
  mov bh, MOUSE_RESOLUTION
  int 0x15
  jc kernel.routine.mouse.init.error

то у меня всё начинает работать как ожидалось.
Кстати в ответе на SO по твоей ссылке вызов этой функции есть, непонятно зачем ты его выкинул.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы