Print function

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
FlashBurn

Print function

Post by FlashBurn »

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]
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Print function

Post by Pype.Clicker »

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

Code: Select all

mov dx, 0x03D4  ;Get Cursor Position MSB
      mov al, 0x0E
      out dx, al
   inc dx
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...
Tim

Re:Print function

Post by Tim »

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:

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
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.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Print function

Post by Pype.Clicker »

Tim, your response confuses me ...
according to http://packetstormsecurity.nl/programmi ... pcode.html,

Code: Select all

DIV     Unsigned divide
  implied    operand       quotient   remainder
   dividend
   AX      /  byte       =      AL     AH
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)
Perica
Member
Member
Posts: 454
Joined: Sat Nov 25, 2006 12:50 am

Re:Print function

Post by Perica »

..
Last edited by Perica on Sun Dec 03, 2006 8:59 pm, edited 1 time in total.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Print function

Post by Pype.Clicker »

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 ...
Post Reply