Problems with BIOS delay function (INT 15h / AH = 86h)
Asked Answered
O

2

1

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.

Osmanli answered 4/12, 2015 at 13:50 Comment(5)
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.Litigant
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.Litigant
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.Litigant
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)Litigant
Int 15h/AH=86h has bugs in DOSBox. Try to use video mode 13 (09h) instead of 19 (13h). That works here.Levin
T
4

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.

Treehopper answered 21/4, 2017 at 13:14 Comment(1)
Nice one! I had the same issue. Calling INT 15 with AH=86h and AL not zero meant I was getting the byte at location 0x186 changing from B9 to 79, changing an instruction from MOV DX, 2710 (B90000h) to JNS nnn (7900000, this changed the instruction to JNS nnn bombing the program at that point. Clearing out to AL=0h and program works flawlessly. Thank you! :)Rezzani
O
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.

Orlantha answered 4/12, 2015 at 15:10 Comment(5)
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 10hOsmanli
@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.Orlantha
@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.Litigant
@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.Orlantha
@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.Litigant

© 2022 - 2024 — McMap. All rights reserved.