#io demo/intro challenge
Since optimizing assembly, algorithmic power, ... Are some of the shared interests we have over at #io.
We decided to hold a bit of a demo challenge.
Submissions so far(alphabetical order)
blasty screenshot 1blasty screenshot 2
dion screenshot 1dion screenshot 2
isadmin screenshot 1isadmin screenshot 2
keegan screenshot 1keegan screenshot 2
leithian screenshot 1leithian screenshot 2
miniBill screenshot 1miniBill screenshot 2
nelhage screenshot 1nelhage screenshot 2
p1ra screenshot 1p1ra screenshot 2
uranix screenshot 1uranix screenshot 2
I'd like to thank everybody who participated!
late entries
bla screenshot 1bla screenshot 2
melissa screenshot 1melissa screenshot 2
brainsmoke screenshot 1brainsmoke screenshot 2
- Author: Peter Ferrie (based on keegan's entry)
- files:binary source
pferrie screenshot 1pferrie screenshot 2
Rules
- Has to run in the MBR of an USB drive (real mode/446bytes)
- Display an IO logo
- Be impressive and as topical as possible.
- Don't be afraid to submit, we aren't experienced demo creators ourselves!
- first submission date is July 20th 2011. However submissions after this date will likely still be processed
Prizes
None. You do however get bragging rights. And submissions will be showcased on this page.
To get you on your way
- A MBR. You can't touch the partition table, or signature.
- What memory looks like at this early stage, is shown here.
- You may want to use the x87 FPU. Using a sine, or some other floating point calculation can go a long way
in implementing a little animation. The x87 can look a little daunting at first though. Central to understanding it. Is that
it uses a small stack of 8 floating point numbers. st0->st7. You can pretend these are registers, however you have to be aware that
any instruction that pushes or pops a value of this stack changes what's in all registers. Here's a quick reference
- If you plan on doing an animation you may require a delay function to make your animation smooth at a fixed speed. I'm going
to suggest you use the bios wait function
. Back in the day we would use the "wait for vsync" method. However it seems that several emulators don't implement this.
For example qemu has this to say:
vga.c-374- case 0x3ba:
vga.c-375- case 0x3da:
vga.c:376: /* just toggle to fool polling */
vga.c-377- val = s->st01 = s->retrace(s);
vga.c-378- s->ar_flip_flop = 0;
vga.c-379- break;
There was a bug in dosbox <= 0.74 in this codepath. If you want to use the bioswait interrupt you may
want to apply this patch.
- Running in qemu:
qemu -hda mbr.img
- Running in kvm:
kvm -hda mbr.img
In kvm it seems to be horribly slow to draw pixels directly into the memory mapped area at 0xA000. Most
likely every write there results in a trap and a call to the usermode utility to draw the pixel. You will
get a huge speed boost using an offscreen buffer and using a rep movsb instruction to copy it to the memory
mapped video buffer.
- Running in bochs:
bochs -q 'boot:a' 'floppya: 1_44=mbr.img, status=inserted'
- Running in dosbox
This can be a bit less demanding than the previous virtualisation/emulation technologies. There are a few ways
to do it, however the most compatible way is using the boot command once in dosbox. You can simplify things
a bit using a config file. But here are some commands to get you started.
dosbox
mount y /tmp
y:
boot mbr.img
- Running in dosemu
A winner on speed, because it uses virt8086 mode. Which is a processor mode that mimics real mode, but it honors
protected mode paging. Hence it's sort of a compatibility mode of x86 processors. So unlike previous solutions
this will not work on non x86 cpu's. And because you need to be able to map at 0, you will also need root
on the system you are testing.
sysctl -w vm.mmap_min_addr=0
Be aware though that setting mmap_min_addr to zero lowers the security of your system. In particular it makes
(local) exploitation of kernel null-pointer dereference bugs a lot easier. Setting this to zero will make
spender twitch. Do restore it to a sane value later.
echo "\$_vbootfloppy=\"$PWD/mbr.img\""> .dosemurc && HOME=. dosemu -A
and even then you aren't done. Apparently dosemu leaves the cpu in a slightly different state than the other
emulation/virtualisation technologies. In particular DS=0x0040 and SS:SP=0x0030:0100. This creates a very
small stack (300 bytes or something). And converting between pointers from the different segments would be
a pain. To get the cpu to a similar state as the others you can add the instructions: xor ax,ax;mov ss, ax;mov ds,ax;mov sp,0x7Bf0
- Running in virtualbox
Virtualbox also often wins on speed. However it's a bit more laboured to get it to work.
I created a little script to speedup testing it in Virtualbox. Just call it with the filename of your mbr and it should
create a vm attach a virtual disk with your mbr in it, run it, wait for keypress and clean everything up.
#!/bin/bash
vmname=iostsdemo
vmfname=1ドル
VBoxManage convertfromraw $vmfname ${vmfname}.vdi
VBoxManage createvm --name $vmname --ostype Other --basefolder $PWD --register
VBoxManage storagectl $vmname --name "IDE Controller" --add ide --controller PIIX4 --sataportcount 2
VBoxManage storageattach $vmname --storagectl "IDE Controller" --port 0 --device 1 --medium ${vmfname}.vdi --type hdd
VBoxManage startvm $vmname
echo "Press any key to clean up the vm"
read -n1 a
VBoxManage controlvm $vmname poweroff
sleep 1
VBoxManage unregistervm $vmname --delete
- Creating a bootable ISO 9660 image out of these intros:
mkdir root
cp mbr.img root
mkisofs -o disk.iso -b mbr.img -c bootcat -no-emul-boot -boot-load-size 4 root/
- simple mbr.asm in nasm syntax
Command to assemble this example:
nasm -f bin -o mbr.img mbr.asm
mbr.asm
BITS 16
mov ax, 0x13
int 0x10
push 0xA000
pop ds
mov bx, 0xfa00
for:
dec bx
mov byte [bx],bl
jnz for
push 'o!'
push ' i'
push 'ai'
push 'oH'
mov bx, 0x02 ; color
mov cx, 8 ; len
mov dx, 0x0f0f; y,x position
push ss
pop es
mov bp, sp
mov ax, 0x1301
int 0x10
hcf: jmp hcf
padding: times 446 - ($-$$) db 0
partitiontable: times 64 db 0xff
signature: db 0x55, 0xaa
- Brainsmoke provides this textmode sample project displaying the challenge announcement
here after building you can run it with a command
like qemu -hda img
- bla (aka me) provides this mbr(source) that contains a simple example of a graphical one:
you can run it with qemu -hda, or simply dosbox filename.com. you should get an output similar to:
mbr sample1
- Debugging using qemu:
start your mbr in qemu using this command:
qemu -s -S -hda mbr.img
argument -s creates a stub for gdb (short for -gdb tcp::1234) , -S waits for gdb to connect before starting the CPU
start gdb, and enter the following commands
set arch i8086
target remote :1234
break *0x7c00
continue
and you will be right at the start of your code, with all the comfort of gdb you are used to.
Help/submissions
Contact us on irc.netgarage.org +6697, or email me on blapost@gmail.com