Text mode cursor problems

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
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Text mode cursor problems

Post by NickJohnson »

I've been having a problem with the text mode cursor. When I am in kernelmode, I can move the cursor fine, by sending the cursor position to the VGA registers like so:

Code: Select all

outb(0x3D4, 15);
outb(0x3D5, cursor & 0xFF);
outb(0x3D4, 14);
outb(0x3D5, cursor >> 8);
I also have it set up so that some usermode processes can access the I/O ports, by setting the IOPL bits in EFLAGS to 3. I checked that the IOPL is in fact 3 from this usermode process. But when I run the exact same piece of code from that privileged usermode process, the cursor does not move. I also do *not* get a general protection fault, which would happen if the IOPL was 0. Is there a reason why it isn't working? I'm using Bochs 2.3.7 - is use of the IOPL bits unsupported or something?

Edit:
Is there a port that I can do I/O to that will give a predictable and reliable value/effect so I can test my setup for something other than this specific case?
earlz
Member
Member
Posts: 1546
Joined: Thu Jul 07, 2005 11:00 pm
Contact:

Re: Text mode cursor problems

Post by earlz »

have you tried using a different emulator? and I would try twiddling the CMOS bits(the free ones) and seeing if that works from usermode (read and write)
manonthemoon
Member
Member
Posts: 65
Joined: Sat Jul 04, 2009 9:39 pm

Re: Text mode cursor problems

Post by manonthemoon »

NickJohnson wrote:Is there a port that I can do I/O to that will give a predictable and reliable value/effect so I can test my setup for something other than this specific case?
Well, in Bochs, there's the 0xE9 debug port, if you have enabled it (debugger must be compiled in).

There's also outputting 0xFE to port 0x64, which should reset the CPU. A quick 'n dirty test to see if any I/O ports are working.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Text mode cursor problems

Post by NickJohnson »

Hmm... interesting. If I write 0xFE to port 0x64, bochs says "unsupported write to keyboard port 64, value = 0". The value doesn't seem to be transmitted correctly, which would definitely cause problems with any I/O. Perhaps my outb wrapper function is incorrect. This is the assembly (nasm) function:

Code: Select all

outb:
	mov dx, [esp+4]
	mov al, [esp+6]
	out dx, al
	ret
And here is the C function prototype:

Code: Select all

extern void outb(u16int port, u8int value);
Is there any problem with that?

Edit: I also tried it under VirtualBox, and the cursor still doesn't move. I don't think it's bochs' fault.
ru2aqare
Member
Member
Posts: 342
Joined: Fri Jul 11, 2008 5:15 am
Location: Hungary

Re: Text mode cursor problems

Post by ru2aqare »

NickJohnson wrote:

Code: Select all

outb:
	mov dx, [esp+4]
	mov al, [esp+6]
	out dx, al
	ret
Are you running this code in 32-bit (protected) mode? If so, the stack has 32-bit alignment, which means that any items with less than 32 bits you push on the stack, such as words and bytes, will be extended to a doubleword. Hence you are loading your arguments from the wrong location. Try this:

Code: Select all

outb proc near
    mov edx, [esp+4] ; upper 16 bits don't matter and this way you can do away with the operand size override prefix 66h
    mov eax, [esp+8] ; upper 24 bits don't matter; and +8 because of the alignment
    out dx, al
    retn ; or retn 8 if you use stdcall
outb endp
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Text mode cursor problems

Post by NickJohnson »

Yep, that was the problem. I didn't know the stack was dword aligned in protected mode... why does that have to be true?
ru2aqare
Member
Member
Posts: 342
Joined: Fri Jul 11, 2008 5:15 am
Location: Hungary

Re: Text mode cursor problems

Post by ru2aqare »

NickJohnson wrote:Yep, that was the problem. I didn't know the stack was dword aligned in protected mode... why does that have to be true?
I'm not sure if this is the correct answer, but probably because you use a data segment whose descriptor's D bit is set, making it a 32-bit data segment.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Text mode cursor problems

Post by NickJohnson »

Actually, I think it is more likely that the push and pop instructions are optimized by having more primitive memory access logic which cannot piece together separate memory bus accesses; i.e. it cannot cross dword boundaries. There's no trouble emulating real mode, because those accesses also cannot cross dword boundaries by not being able to cross word boundaries, and not being able to push/pop dwords. Maybe Intel decided the speed of the stack was more important than its memory efficiency (which I would agree with).
ru2aqare
Member
Member
Posts: 342
Joined: Fri Jul 11, 2008 5:15 am
Location: Hungary

Re: Text mode cursor problems

Post by ru2aqare »

NickJohnson wrote:Actually, I think it is more likely that the push and pop instructions are optimized by having more primitive memory access logic which cannot piece together separate memory bus accesses; i.e. it cannot cross dword boundaries. There's no trouble emulating real mode, because those accesses also cannot cross dword boundaries by not being able to cross word boundaries, and not being able to push/pop dwords. Maybe Intel decided the speed of the stack was more important than its memory efficiency (which I would agree with).
I don't think you are right. You can load esp with (for example) 0xFFFF and do doubleword push/pop operations to your hearts content. Actually, most beginner assembly users do the same thing in real mode - load sp with 0xFFFF as they think it's the highest possible value of sp in a 64K stack segment (which it is not - loading sp with 0x0000 lets you utilize the full 64K stack available, because the processor automatically decrements sp by 2 before doing a memory write).
manonthemoon
Member
Member
Posts: 65
Joined: Sat Jul 04, 2009 9:39 pm

Re: Text mode cursor problems

Post by manonthemoon »

NickJohnson wrote:Yep, that was the problem. I didn't know the stack was dword aligned in protected mode... why does that have to be true?
All I can say is RTFM :wink: . Intel Software Developer's Manual (vol 2B, "PUSH") describes the operations of the stack in great detail. The stack is not automatically aligned, you can very well write "PUSH AX" with a 32-bit stack, and ESP will go down by two bytes instead of four.

By messing with the D/B flags of your CS and SS descriptors, and by using the 66h operand prefix, it's possible to push a 16-bit value onto a 32-bit stack and vice versa. Doing so would misalign everything after, which is not desirable (performance and also calling conventions).

As far as C calling conventions go, passing a char, short, or int makes no difference to the stack because anything shorter than 32-bits gets sign extended (or maybe zero extended?). So your original code would work, but only if it were called using assembly code that could write directly to the stack.

In C, however, all parameters are sizeof(int) for the sake of stack consistency (and the fact that the compiler has no way of knowing the types of parameters without C++ name mangling). But the processor couldn't care less what sizes you push and pop, this is a C/C++ issue.
Post Reply