0

I began studying assembly this year in my school, and we just started learning about pixels.

Our teacher gave us some code and told us to mess around with it, he also told us to try and implement delay in the code(ah=86h|int 15h), but when i tried to use it the location and colors of some pixels got changed, and i don't understand why

code: (just a piece of the code, there is some more there also get's ruined after the delay)

mov cx,  20

add [y], 2
mov dx, [y]

paint1RowOf10:

mov bh, 0h 
mov bx, cx

add [x], 1
mov cx, [x]

add [y], 4
mov dx, [y]

mov ax, [red]
mov ah,0ch 
int 10h 

    ; here is a delay part, it waits for 1 seconde
    ; from the help of assembly:
    ; INT 15h / AH = 86h - BIOS wait function. 
    ;CX:DX = interval in microseconds (these are notes from my teacher)

mov ah, 86h
mov cx, 1
mov dx, 2
int 15h 

mov cx, bx
loop paint1RowOf10    

This is the result http://prntscr.com/9a8lpw can you tell me why does this happen? because as far as i see, the pixels are supposed to go in one line, and not change colors.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Hadarsi320
  • 343
  • 1
  • 5
  • 10
  • 1
    This looks like a problem `mov bh, 0h;` followed by `mov bx, cx`. . First you move 0 to _BH_ for the `int 10h/ah=0ch call` (BH=page number). That is fine, then right after that you overwrite ALL of _BX_ (including _BH_ and _BL_) by doing `mov bx, cx` . _BL_ and _BH_ are parts of the _BX_ register. Moving something into _BX_ will trash _BH/BL_ . Either push _CX_ on the stack (and pop it later) or use a register other than _BX_ as temporary storage (in this case _SI_ or _DI_) look safe with code given. – Michael Petch Dec 04 '15 at 15:53
  • I say _look safe_ but you don't show all your code so they may not be safe. You have to make sure that whatever you use isn't being used (or will be clobbered) in the code you are showing (and the parts you didn't). It would be better to just amend your question to show all your code, that would make it at least a verifiable complete example. – Michael Petch Dec 04 '15 at 16:06
  • 1
    If you want to increase your chances of getting a solution, please post all your code, not just a snippet. Although there are potential issues in the code shown, without seeing the rest of your program it will be harder for people to help. – Michael Petch Dec 04 '15 at 16:22
  • Without the rest of the code, there is the possibility of things going very badly here if X and Y are defined as bytes (and not words). If you don't feel compelled to provide all your code then I recommend you consider stepping though the code with a debugger (Turbo debugger does a reasonable job) – Michael Petch Dec 04 '15 at 16:44
  • `Int 15h/AH=86h` has bugs in DOSBox. Try to use video mode 13 (09h) instead of 19 (13h). That works here. – rkhb Dec 04 '15 at 17:31

2 Answers2

3

There is a weird fact, about int 15h ah=86h you also need to set al=0, unless it get an erratic behavior

Delay Code:

mov al, 0 mov ah, 86h mov cx, 1 mov dx, 2 int 15h

I discovered it with try-and-error method and I realize when al=0 it works.

0

Try using a debugger to make sure all the registers still have the values you expect, after the int 10h system/BIOS call (whatever it is). I haven't checked docs, but it may clobber some other registers?

Or maybe your problem is:

mov ax, [red]
mov ah,0ch 
int 10h

Remember that ah is the high half of ax. So if you modify ah right after loading something into ax, it's YOUR code that modified your color value.


Also, code like

add [y], 2
mov dx, [y]

is horrible. Try to keep variables in registers when you can. If you need to spill some, try to avoid doing it with variables that change every time through the loop.

mov dx, [y] 
add dx, 2 
mov [y], dx

Would be somewhat better, because dx would come from the first load, not a chain of read-modify-write -> load. It is more instructions, which is why keeping important loop variables in memory is bad.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • al is for the color and ah does the actual action. it is written this way only because red is a dw, and not db, if it were, it would just be: mov al, [red] || mov ah,0ch || int 10h – Hadarsi320 Dec 04 '15 at 15:46
  • @user5561744: why are you doing a 16bit load if you don't want all 16b? `mov al, [red]` if you just want to set `al`. If you need to convince MASM that you know what you're doing, you might need `mov al, byte ptr [red]`? IDK. – Peter Cordes Dec 04 '15 at 15:55
  • @PeterCordes : Although it is bad style (I completely agree) he lucks out. The color is just a byte (although he defined it as a word). The portion that matters will be loaded into the bottom half of the register (_AL_). Then he modifies the top half for the _INT_ call. So although unorthodox and poor way of doing it, I do not think it is his problem in this case. I concur with defining the colors as a byte and then using `byte ptr`. – Michael Petch Dec 04 '15 at 16:11
  • @MichaelPetch: I wasn't saying it wouldn't work. :P I was saying it was dumb and made the code harder for a human to read. But yeah, if you only need a byte of storage there ever, then only reserve one. – Peter Cordes Dec 04 '15 at 16:14
  • 1
    @PeterCordes : I was just pointing it out. btw, *int 10h/ah=0ch* doesn't destroy any registers upon returning (so one only has to worry about clobbering registers setting up the inputs). *Int 15h/ah=86h* only modifies _AX_ upon returning. – Michael Petch Dec 04 '15 at 16:20