Tryin to do an XOR texture in DOS

category: code [glöplog]
I've just started learning assembly and my first goal was to do a simple XOR texture in DOS 13h mode but it's not working out that well.

This is the current state of my code (only tested in DOSbox with fasm): http://pastebin.com/E8LxQvBk

It actually draws a XOR texture (it does look pretty weird though, maybe because of the 13h color palette). The problem is that it is drawing each frame with and offset to the previous (can be seen in DOSbox with low cycles). This results in a lot of flicker when I'd expect (and want) it to be static.

Can anybody figure out what I'm doing wrong since I'm not capable?
added on the 2012-01-11 20:11:11 by paldepind paldepind
added on the 2012-01-11 20:29:40 by paldepind paldepind
added on the 2012-01-11 20:34:54 by Pirx Pirx
Download link doesn't work. Tried all the mirrors.
added on the 2012-01-11 20:38:20 by paldepind paldepind
added on the 2012-01-11 20:41:53 by Pirx Pirx
Thank you! It's interesting but it doesn't really help me figure out what's wrong with my current program..
added on the 2012-01-11 20:55:53 by paldepind paldepind
Tip for your code: under DOSBox you see kind of animation because DX and DI are not initialized. Put 0 to them before loop1, also mov dx,0 instead of mov dx,1 at the end. Anyway, for static picture no need to outer loop, wait for key by using int 16h for example.
added on the 2012-01-11 21:03:14 by Pirx Pirx
About the mov dx,1 I now that's wrong. I only changed it out of desperation when the code wasn't working and forgot to change it back. The reason for the outer loop is that the code is supposed to evolve into a plasma effect when the XOR texture is finish :D

Setting DX and DI to zero before the looped as you suggested fixed it! It is now working as it should! However I don't understand why and uninitialized DX and DI register would create this problem. Could you (or somebody else) please explain why?
added on the 2012-01-11 21:32:43 by paldepind paldepind
For some registers, like AX, you can assume that they contain 0 at startup, but for many, like DX, you cannot. DX is the point here - it can contain values in range 0-65535, and you reset it and go to next frame only when DX=200, otherwise you increment and draw new line. Imagine that DX is little bigger than 200 at startup - what then?
added on the 2012-01-11 22:00:39 by Pirx Pirx
Usually we can assume that at startup
ah = 0
al = ?
bx = 0
cl = 255 (ch is often = 0)
dx = ?
si = 256
di = -2
bp = ?
sp = -2
This assumption can save a lot of bytes in small intros.
added on the 2012-01-11 22:09:32 by frag frag
Ahh! I get it now. Makes sense.

I have anyother tiny question: In my code I use the two lines
Code:mov ax, 0a000h mov es, ax

This makes sense to me because the 13h video mode starts at 0a000h and 'stosb' which writes to the video uses ES as an offset. But in a tutorial I found they were instead using "les bp,[bx]". I've looked up les and watched the code execute in my debugger but I can't figure out why this command works as an (more space efficient) replacement of the two lines I used.
added on the 2012-01-11 22:14:59 by paldepind paldepind
Thanks going through all the registers frag!
added on the 2012-01-11 22:16:41 by paldepind paldepind
stosb uses ES as segment rather than as offset. Which tutorial are you looking at? les bp,[bx] is kind of trick which loads ES with value near the 0A000h, but avoid to use it unless you code 32B intro. The display result can be different under different operating systems. Best to use (4 bytes):
push 0A000h
pop ES
added on the 2012-01-11 22:27:07 by Pirx Pirx
This is the tutorial the tutorial is very superficial tough and the trick is not explained at all.

I'll use the push pop you suggested instead.
added on the 2012-01-11 22:32:54 by paldepind paldepind
I was always mov es,ax but oneday when I was curious to see the code of some very tiny 32b I noticed the les bp,[bx] and was like wtf? I searched on the net what les bp,[address] does and I guess it's also assuming stuff that might not work always..
added on the 2012-01-11 23:16:56 by Optimus Optimus
I am still not exactly sure how les bp works on 32b tros.
added on the 2012-01-11 23:18:22 by Optimus Optimus
The startup state is like this (? = undefined):

EAX = EBX = ????xxyy
xx = 00 if first FCB has valid drive letter, FF if not
yy = 00 if second FCB has valid drive letter, FF if not

If the program is run without any arguments (e.g. from WinXP), you can assume AX=BX=0.

ECX = ????00FF
EDX = ????zzzz
zzzz = CS=DS=ES=SS = current segment (between 0080 and 9000, usually not larger than 4000).
ESI = EIP = ????0100
EDI = ESP = ????FFFE
EBP = ????09?? (usually 090A, 090E or something like this)
flags: DF=0 (stosb and friends go up), IF=1 (interrupts on), others are ?

The FPU stack is ? - you need to run finit if you use it.

Memory layout:

word CS:[FFFE] = SS:[SP] = 0000
word CS:[0000] = 20CD = "int 20h", so "ret" = "pop ip" ends the program if you didn't change SS or SP
word CS:[0002] = MemTop = first segment that doesn't belong to our program (usually 9FFF on WinXP/DOSBox or A000 in pure DOS)

This is "les" trick: "les reg,[bx]" does "reg = DS:[BX], es = DS:[BX+2]". BX is 0, so ES will become MemTop. You can then address the screen using ES (any segment around A000 will do for 32b intros).

The rest up to CS:[0100] are various DOS things like FCBs (file control blocks), some may be constant. CS:[0080] up to CS:[00FF] contains the command line padded with zeroes, so you can usually expect CS:[00C0] to CS:[00FF] to be 0.

The program is loaded from CS:[0100] (CS:SI). It's nice to put constants in the first 128 bytes where they can be addressed with "[si+byte]" or "[bx+si+code]".
added on the 2012-01-12 02:29:54 by rrrola rrrola
paldepind: its more space efficient because it takes only two bytes. however as rrrola and others have pointed out the registers may have undefined values at startup, causing your effect or whatever to behave differently. but it usually doesnt matter because your code takes care of that.

les = load register and es with words from memory

Code: push 0a000h pop es ;4 bytes les bp,[bx] ;2 bytes mov ax, 0a000h mov es,ax ;5 bytes mov ah, 0a0h mov es,ax ;4 bytes. al=?

added on the 2012-01-12 12:25:10 by rudi rudi
plade, that tutorial is wrong in so many ways (and mode 13h is not mode-x)
i mean the code should not care about it.
added on the 2012-01-12 12:27:22 by rudi rudi
I understand it now :D

rasmus: Yes, I'm aware of that. But the resulting code worked and it was useful.
added on the 2012-01-12 16:54:11 by paldepind paldepind
Arg! I've managed to screw it up again. I changed the code so that it instead of storing both x and y coordinates separately only store one "coordinate" and then extract x and y from it by dividing it. This however caused the visuals, once again, to flicker.

This might be similar to my previous problem but as far as I can see I've initialized all relevant registers.

Here's the updated code: http://pastebin.com/njSdUtFj
added on the 2012-01-13 17:10:02 by paldepind paldepind
Flicker? Sounds like you need to wait for vertical retrace.