Author Topic: Why I can not switch to 32-bit in real mode?  (Read 16313 times)

nobody

  • Guest
Why I can not switch to 32-bit in real mode?
« on: March 11, 2008, 01:30:29 PM »
the asm source is as below
---
org 0100h;
jmp BEGIN;

ALIGN   32
[bits 32]
BEGIN :
   mov ax, 0b800h
   mov gs, ax

mov edi, (80*10+10)*2
   mov ah, 0ch
   mov al, 'P'
   mov [gs:edi], ax

mov edi, (80*10+11)*2
   mov ah, 0ch
   mov al, 'Q'
   mov [gs:edi], ax

mov edi, (80*10+12)*2
   mov ah, 0ch
   mov al, 'R'
   mov [gs:edi], ax

jmp $
===
As you can see, I used ``bits 32'' and ``align 32'' in real mode.
but it does not work. Please tell me why.
Thanks.

nobody

  • Guest
Re: Why I can not switch to 32-bit in real mode?
« Reply #1 on: March 11, 2008, 06:36:36 PM »
Real mode is 16-bit.

What you've got there looks like a dos .com file. Lose the "bits 32", and it ought to work.

If, if fact, you want to switch from real mode to protected mode (16- or 32-bits... you want 32, of course. 16-bit pmode exists, but isn't much used), we can provide an example of that. I see no sign of trying to do so in this code.

Assuming you're running Windows, or Linux, or BSD, or MacOSX, or so - you're already *in* 32-bit protected mode. The bad news is, you can't access hardware directly. If you *could* shove a pixel/character onto the screen directly, you wouldn't want to - might not be "your turn". "Protected mode" is protected from *us*, I'm afraid!

The fact that you end with "jmp $" suggests that maybe this is intended to run from a bootsector. That *would* allow you to switch to 32-bit mode, but not as simply as saying "bits 32". You'll have to create and load a Global Descriptor Table, alter cr0, make a far jump to reload cs with a 32-bit code selector. Now we're in 32-bit mode! But... you can't *do* much (like enable interrupts - they've got to be disabled for this) without providing 32-bit code to handle interrupts and load an IVT... Unless you're writing an OS, you don't want to mess with it!

If, by some chance, you've already switched to 32-bit pmode, you'd want to load gs with a selector pointing to a descriptor with a "base" of zero, and use 0xB8000 as an offset (the common way), or with a base of 0xB8000 and start from offset zero. Unless you've got a *lot* of descriptors in your GDT, 0B800h will not be a valid selector!!!

The CPU is in 16-bit mode or 32-bit mode, depending on cr0 and (if cr0 & 1) a bit in the code descriptor. We tell Nasm whether we want to generate 16- or 32-bit code with "bits 16" or "bits 32" (default varies with output format - 16-bits for "-f bin"). They'd *better* match!!!

If you don't understand why, try disassembling your code with "ndisasm -b 16 -o 100h myfile.(com? bin?)". This is what the CPU will see if it encounters your code in 16-bit mode. Now try it with "-b 32". Try it with and without "bits 32" in your file. Notice how many bytes are used to store, for example, "0B800h". See why "mix and match" won't work?

So... what are you trying to do?

Best,
Frank

(incidentally, with "org 100h", you're already aligned to 256 bytes, so "align 32" isn't going to do anything...)

nobody

  • Guest
Re: Why I can not switch to 32-bit in real mode?
« Reply #2 on: March 12, 2008, 05:22:16 AM »
> Why I can not switch to 32-bit in real mode?

Because your code switches NASM only, but not the CPU. ;-)

NOTE 1 : You __can__ use 32-bit registers like EAX or EDI in use16 code also (safe on >=80386, but mostly not the best idea, still)

NOTE 2 : With use16, you __can't__ use indexing above segment limit: "mov [gs:edi], ax" won't work for EDI>0xFFFF

NOTE 3 : You __can__ switch to something like "32-bit real/unreal" mode, but from __REAL__ mode only, not from NTVDM/DOSEMU/EMM386 crap

Frank already explained you the rest ;-)