Author Topic: 64-bit and 32-bit in 16-bit DOS help.  (Read 9243 times)

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
64-bit and 32-bit in 16-bit DOS help.
« on: December 09, 2010, 01:54:56 PM »
I was wondering how to run 32 bit and 64 bit programs in DOS correctly, I have tried to do this, but seems to not work. Here is my code:
Code: [Select]
[BITS 32]
AppMain:
mov ax, A000h
mov es, ax

mov ax, 13h
int 10h

mov ah, 1
mov edi, 0

FillScreen:
mov [es:edi], ah
add edi, 1
cmp edi, 64000
jb FillScreen

IdleProcess:
jmp IdleProcess
I ran it in DOSBox while assembled in 32-bit and got a blank screen. It works when assembled in 16-bit though.
« Last Edit: December 09, 2010, 02:02:48 PM by ThatGuy22 »

Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #1 on: December 09, 2010, 04:27:40 PM »
I was wondering how to run 32 bit and 64 bit programs in DOS correctly, I have tried to do this, but seems to not work.

That's because just telling NASM to write 32-bit code isn't enough; you cannot expect the CPU and OS to magically know that it is encoded as 32-bit code. (That doesn't work in any output format.) Note how, in the example below, the 32-bit code section ("bits 32") begins behind a specific function call which changes the CS selector to 32-bit operation. Depending on the output format and section declaration, the operating system might expect (default to) any encoding; for example, a 32-bit Windows program (PE file format) is expected to contain 32-bit code.

Depending on what you want to achieve, writing 32-bit or 64-bit programs for your actual operating system might be more appropriate and convenient now. But as you asked for bothering with DOS, I'll tell you what you need for bothering with DOS.

Inform yourself about the DOS Protected Mode Interface (DPMI). DPMI provides the easiest way to write 32-bit user mode DOS programs. DJGPP's reference might be useful, otherwise look up the Interrupt 31h functions in Ralf Brown's Interrupt List.

The attached example demonstrates a bare minimum of DPMI calls necessary to enter 32-bit protected mode. The example compiles to a flat .COM file. (This may or may not work in DOSBox, but if it doesn't work it's their fault. Try booting a real DOS inside DOSBox then, or using a sane emulator.)

Note that your example sets ES to the value "A000h" which is not valid NASM syntax.

Note that your example sets ES to the value "0A000h" which is valid in Real Mode to access the memory at address A0000h. In Protected Mode, A000h is most likely not a valid selector; an access would therefore cause an exception. The video memory might be mapped to the address A0000h in a DPMI environment too; but you have to set up a selector to work with that yourself.

Note that your example hangs the machine at the end. You might want to use Int21.4C00 (Terminate DOS process) instead, like in the attached example.

There is no standard for 64-bit programs in DOS - you would have to write a memory manager or DOS extender or DPMI host yourself; basically, you would have to write your own (64-bit, protected mode) operating system.
C. Masloch

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #2 on: December 09, 2010, 05:36:27 PM »
Wow, this is a lot more complex than I thought. Thank you I will try to get it to work with 32-bit, but with my luck I probably will not be able to.

Thanks anyway.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2436
  • Country: us
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #3 on: December 09, 2010, 06:32:37 PM »
That's kewl, Christian! Wish I'd had that years ago!

Someguy, you don't say what command line you're giving Nasm. "-f coff", and link it with DJGPP might almost have worked. I'm guessing "-f bin". When dos sees a filename ending in .com or .exe, it doesn't load it according to the extension (command.com has been an .exe for years!), but according to the signature in the first two bytes, if it's "MZ" (or "ZM", I'm told) it looks further for a "PE" signature to decide whether to load it as 16 bits or 32. If it doesn't see "MZ", it loads it as a 16 bit .com file. Regardless of how many bits you told Nasm!

An example might illustrate what you're up against...

Code: [Select]
; nasm -f bin -o myfile.com myfile.asm
bits 16

mov ax, bx
mov ax, 0A000h
nop
nop
nop

bits 32
mov ax, bx
mov eax, ebx
mov ax, 0A000h
mov eax, 0A000h
nop
nop
nop

Nasm will do both 16 and 32 in one shot.  Ndisasm will not. By default, it'll disassemble as 16 bits - same as what your CPU will see if it's in 16-bit mode:

Code: [Select]
00000000  89D8              mov ax,bx
00000002  B800A0            mov ax,0xa000
00000005  90                nop
00000006  90                nop
00000007  90                nop
00000008  6689D8            mov eax,ebx
0000000B  89D8              mov ax,bx
0000000D  66B800A0B800      mov eax,0xb8a000
00000013  A00000            mov al,[0x0]
00000016  90                nop
00000017  90                nop
00000018  90                nop

As you can see, it gets a little confused when it gets to the part we told Nasm to assemble as "bits 32"! If you attempted to execute this code with the CPU in 32-bit mode, it'd see what "ndisasm -b 32 myfile.com" sees:

Code: [Select]
00000000  89D8              mov eax,ebx
00000002  B800A09090        mov eax,0x9090a000
00000007  90                nop
00000008  6689D8            mov ax,bx
0000000B  89D8              mov eax,ebx
0000000D  66B800A0          mov ax,0xa000
00000011  B800A00000        mov eax,0xa000
00000016  90                nop
00000017  90                nop
00000018  90                nop

Now the 16-bit part is wrong! You didn't have a 16-bit part in your attempt, but if you'd executed it with the CPU in 32-bit mode, when you did the "int 10h", it would be 16-bit code... which would be misinterpreted and you'd soon crash.

You can start off in 16-bit mode - a bootsector, say, or "real real-mode dos" - and switch the CPU to 32-bit (protected) mode, but you won't have int 10h... or any other interrupt, until you provide them. Since the hardware generates interrupts frequently, the first thing you'll do before entering pmode is "cli"... and don't "sti" until you've got some Interrupt Service Routines in place. I've never gotten that far...

Best,
Frank


Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #4 on: December 10, 2010, 01:15:56 PM »
Someguy, you don't say what command line you're giving Nasm. "-f coff", and link it with DJGPP might almost have worked.

Yes, it might. In that case, DJGPP's ld will link in DJGPP's run-time code and create an executable which consists of an "MZ stub" as well as the "real" program. The latter is your application plus some of DJGPP's Protected Mode support code (and libraries). The "MZ stub" is a DOS program that switches into Protected Mode using DPMI (like my example) and starts up the application afterwards.

Now the 16-bit part is wrong! You didn't have a 16-bit part in your attempt, but if you'd executed it with the CPU in 32-bit mode, when you did the "int 10h", it would be 16-bit code... which would be misinterpreted and you'd soon crash.

You mean the interrupt 10h BIOS handler? But the Protected Mode IDT would have to be set up (incorrectly) to execute the BIOS code in protected mode for that to happen. (If the IDT wasn't set up at all, you'd probably just triple-fault on the first interrupt.)

In a DPMI environment, the Protected Mode IDT is by default set up to redirect (most) software interrupts to the V86/Real Mode handler - but this redirection does (temporarily) switch to the right mode (ie V86 or Real Mode). Therefore, you can just use an "int 10h" instruction with the appropriate register values. (This does not work if you have to pass the V86/Real Mode handler any segment registers or if they return any segment registers that you want to use.)

You can start off in 16-bit mode - a bootsector, say, or "real real-mode dos" - and switch the CPU to 32-bit (protected) mode, but you won't have int 10h... or any other interrupt, until you provide them. Since the hardware generates interrupts frequently, the first thing you'll do before entering pmode is "cli"... and don't "sti" until you've got some Interrupt Service Routines in place. I've never gotten that far...

I think the exercise of writing your own protected mode "operating system" is abnormally popular, for I find it far too complex. If you want something simple, write applications - or a boot sector which stays in Real Mode.
C. Masloch

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #5 on: December 10, 2010, 05:59:10 PM »
Ok so I have to switch the CPU to 32-bit mode, how is this done?

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #6 on: December 11, 2010, 12:56:23 AM »
Ok so I have to switch the CPU to 32-bit mode, how is this done?

Search OSDev.org. I would suggest reading as much as you can there so you know where to find the information again.

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #7 on: December 11, 2010, 11:21:55 PM »
I did search there and at most I found an example of 32 bit code, but I did not see any difference with it, it was just like coding in 16 bit except with 32 bit registers. Nothing different other than that. I have not really tested there code, but supposing it works what makes it work without doing all the technicalities of what Frank Kotler said?

 -The code I was referring to is found here:
       http://wiki.osdev.org/Babystep4

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #8 on: December 12, 2010, 12:12:04 AM »

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #9 on: December 12, 2010, 03:25:17 PM »
Ok I see how to now, you need to set special bits on the CPU to tell it what mode you want.

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #10 on: December 12, 2010, 05:49:46 PM »
Ok I see how to now, you need to set special bits on the CPU to tell it what mode you want.

Yes, among many many other things. This topic isn't something you will learn effectively by muddling your way through. Please review the Intel and/or AMD processor documentation, they explain everything quite clearly.

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #11 on: December 12, 2010, 07:49:05 PM »
So this is a thing I will NEED to know most defiantly. So what is this topic called so I can search it on google if I need help. I remember you saying something about DJGPP is that what it is called?

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #12 on: December 12, 2010, 09:08:51 PM »
Frank mentioned DJGPP.

You'll want to research things like DPMI, DOS/4G, Unreal Mode, etc.

Most of these topics fall under the operating system development umbrella, for which I already gave you the most valuable modern resource: OSDev.org. Make sure you search the OSDev.org Wiki and Forums. You'll find that the basic programming questions you are asking have been answered a thousand times over.

Offline ThatGuy22

  • Jr. Member
  • *
  • Posts: 40
Re: 64-bit and 32-bit in 16-bit DOS help.
« Reply #13 on: December 13, 2010, 12:40:47 AM »
Ok and yes, osdev.org is useful, but what I don't like is that not all code examples are in assembler some are in C++ and I'm not too advanced it that.