[font=small]Note : if this is too much off topic, please tell me, I'll move it into a new topic.[/font]
thepowersgang wrote:
My friend, this is one of the most clever tricks I have seen for quite a while!
We could do with a size hacks wiki page or something like that for these things.
Thanks
I actually spent a whole day on it, maybe two...
I investigated the following possibilities, in approx. order of size, decreasing :
Trivial, unoptimized, but you can easily change the keycodesCode:
cmp ah,KEYCODE_UP
jne .1
inc dx
.1
cmp ah,KEYCODE_DOWN
jne .2
dec dx
.2
cmp ah,KEYCODE_RIGHT
jne .3
inc bx
.3
cmp ah,KEYCODE_LEFT
jne .4
dec bx
.4
A "tree" of bit-testing hacksChoose HACK1 so that :
Code:
0 == (HACK1 & KEYCODE_UP) == (HACK1 & KEYCODE_DOWN)
1 == (HACK1 & KEYCODE_LEFT) == (HACK1 & KEYCODE_RIGHT)
Choose HACK2 so that :
Code:
0 == (HACK2 & KEYCODE_UP)
1 == (HACK2 & KEYCODE_DOWN)
Choose HACK3 so that :
Code:
0 == (HACK3 & KEYCODE_LEFT)
1 == (HACK2 & KEYCODE_RIGHT)
Code:
mov al,ah
and al,HACK1
jnz .horizontal
and ah,HACK2
jnz .down
inc dx
.down
dec dx
.horizontal
and ah,HACK3
jnz .right
dec bx
.right
inc bx
Choose jump adress hackThe arrow keys scancodes have the following property : if you zero out their least significant bit, then they each have their first bit counting from the right in a different position. Luckily, the 'bsf' (bit search forward) instruction returns the position of the rightmost set bit.
010
1 0000 DOWN
0100
1000 UP
0100 1
101 RIGHT
0100 10
11 LEFT
Code:
mainloop:
; Do something
; Check for next key
mov ah, 0x01
int 16h
jz mainloop
; Manage pressed key and jump back to mainloop
xor ax,ax
int 16h
and ax, 0x1e00 ; keep bits 1,2,3 and 4
bsf ax, ax ; see top of the file to see why this works...
shl ax,1 ; each case takes two opcodes (inc/dec, ret)
add ax, .do_movements - 16 - 2
call ax
jmp short mainloop
; the 'call' just above will call one of these.
.do_movements:
dec bx
ret
inc bx
ret
dec dx
ret
inc dx
ret
Dynamic code generationThe hack I used
Code as data hackI didn't try this one.
Principle : when you have some random data, say the adress of your back buffer, you can actually put a value that represents one or severall opcodes. Then, at some point, you jump onto those opcodes. better be a jump you must do anyway, cause otherwise you'll use up two bytes for the extra jump.
It's even better if you can dynamically generate an opcode just before those data-code bytes