I have a big problem with my print function. When I test multitasking my 2 tasks will run a few seconds, but then I get a int 0 exception. So the problem have to be in my print function. I attached my code.
[attachment deleted by admin]
Print function
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Print function
i can remember of that function, and i also remember i suggested you not to rely on the VGA cursor position to remember where your last char should go.
Now that you're multitasking, you may find in the situation of one task starting one I/O command
and then it is interrupted and tasks switch before it can issue its "in al,dx" command.
When the state will be restored, there are little chances the VGA register will still be ready to perform the right "in" command...
Fortunately enough, you were only playing with the cursor... try to imagine the mesh you could have done if this was a HDD programming routine ...
The best workaround i can see for you would be to start a CLI section every time you're going to access I/O registers ...
However, you'll have to rewrite that messy print function sooner or later, imho...
Now that you're multitasking, you may find in the situation of one task starting one I/O command
Code: Select all
mov dx, 0x03D4 ;Get Cursor Position MSB
mov al, 0x0E
out dx, al
inc dx
When the state will be restored, there are little chances the VGA register will still be ready to perform the right "in" command...
Fortunately enough, you were only playing with the cursor... try to imagine the mesh you could have done if this was a HDD programming routine ...
The best workaround i can see for you would be to start a CLI section every time you're going to access I/O registers ...
However, you'll have to rewrite that messy print function sooner or later, imho...
Re:Print function
int 0 is the divison by zero exception. More accurately, int 0 is generated by the DIV instruction when the result is too big to store in the quotient register. I searched for 'div' in your listing and I came up with this:
Here, you're dividing AX by BH and storing the quotient in AL and the remainder in AH. The top half of AX (i.e. AH) is undefined in this procedure, so it's entirely likely that the result of the division won't fit into AL.
The solution is to set AH to zero before you divide.
Code: Select all
getxy:
mov dx, 0x03D4 ;Get Cursor Position MSB
mov al, 0x0E
out dx, al
; mov dx, 0x03D5
inc dx
in al, dx
shl ax, 8 ;Store MSB in ah
; mov dx, 0x03D4 ;Get Cursor Position LSB
dec dx
mov al, 0x0F
out dx, al
; mov dx, 0x03D5
inc dx
in al, dx ;Store LSB in al
mov bh, 80 ;Divide to get XY coordinates (X in ah and Y in al)
div bh
ret
The solution is to set AH to zero before you divide.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Print function
Tim, your response confuses me ...
according to http://packetstormsecurity.nl/programmi ... pcode.html,
the top half in his input AX isn't undefined : he shifted the "MSB" from al into ah... (though mov ah,al would have been clearer
note: (whether the second character has a cursor position of 1 or 2 is still unknown to me, it would be wise to check it by asking the BIOS to set the cursor somewhere and read the cursor location with VGA registers)
according to http://packetstormsecurity.nl/programmi ... pcode.html,
Code: Select all
DIV Unsigned divide
implied operand quotient remainder
dividend
AX / byte = AL AH
note: (whether the second character has a cursor position of 1 or 2 is still unknown to me, it would be wise to check it by asking the BIOS to set the cursor somewhere and read the cursor location with VGA registers)
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Print function
in a multitasking system, it's usually wise to make sure only one task talks to one device. This is usually be done by either serializing accesses (making sure accesses are mutually exclusive with the help of a semaphore, a spinlock or by disabling interrupts) or by centralizing the access (only one task will have the rights to do I/O on a given device, any other task will have to send requests messages to that task so that it performs access for it).
If you're a user-level application, you usually don't see the I/O ports (and the kernel can use the IOPL and the IO bitmap on IA-32 to enforce this), nor do you see memory-mapped resources like VRAM. Instead, you use a hardware abstraction layer provided by the kernel such as a Console, a print spooler, /dev/dsp or whatever ...
In some very specific cases, you might delegate the access to one resource to a user application (for instance when you switch an application to "full screen" mode, you might give it the VRAM buffer rather than some off-screen memory so that the display is faster) -- but then it's up to the kernel to make sure it gives the control to a *single* application ...
If you're a user-level application, you usually don't see the I/O ports (and the kernel can use the IOPL and the IO bitmap on IA-32 to enforce this), nor do you see memory-mapped resources like VRAM. Instead, you use a hardware abstraction layer provided by the kernel such as a Console, a print spooler, /dev/dsp or whatever ...
In some very specific cases, you might delegate the access to one resource to a user application (for instance when you switch an application to "full screen" mode, you might give it the VRAM buffer rather than some off-screen memory so that the display is faster) -- but then it's up to the kernel to make sure it gives the control to a *single* application ...