Author Topic: Some questions about 16bit DOS programming  (Read 8498 times)

Offline ben321

  • Full Member
  • **
  • Posts: 100
Re: Some questions about 16bit DOS programming
« Reply #15 on: March 24, 2015, 08:35:30 PM »
I'm glad to see that block of comments near the top of your earlier version gone. It was almost completely wrong.
I wasn't sure about its accuracy, so I removed it in my revised version of the code. If you could tell me specifically what was wrong with it, that would be helpful, so I could learn something.

There's still a sort-of error in it, but it doesn't do any harm.
Code: [Select]
    mov [di], ax
In mode 13h, each pixel is one byte. You write the pixel you're interested in from al, and then write the next pixel from ah (which you have zeroed). But then you advance one pixel and overwrite the "extra" one with what it's supposed to be, so it really doesn't matter. If you were setting pixels individually, you probably wouldn't want to set two... unless intentionally.[/code]

So I should be using al instead of ax? Like this?
mov [di], al

Would this work too? Specifying that the size of the transfer should be byte sized?
mov byte[di], ax

Also, in this case the extra byte always has the value 0x00, so it gets overwritten anyway on the next iteration, but I assume this might be a problem for other programs?

Anyway, I wrote it to a floppy with "dd" and it works on real hardware here...
COOL!
« Last Edit: March 24, 2015, 11:46:13 PM by ben321 »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2359
  • Country: us
Re: Some questions about 16bit DOS programming
« Reply #16 on: March 24, 2015, 11:16:42 PM »
Code: [Select]
mov byte [di], ax
What happens when you try it? Oh,darn! Those guys who wrote Nasm screwed you up again! :) You might want to try disassembling the two instructions (al and ax). While the mnemonic "mov" is the same, they're two different opcodes...

As for the comments I didn't like... I'm not in the mood right now. I think you'll get it as you learn how a bootsector does work. If not, ask again.

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 100
Re: Some questions about 16bit DOS programming
« Reply #17 on: March 24, 2015, 11:53:22 PM »
Code: [Select]
mov byte [di], ax
What happens when you try it? Oh,darn! Those guys who wrote Nasm screwed you up again! :) You might want to try disassembling the two instructions (al and ax). While the mnemonic "mov" is the same, they're two different opcodes...

As for the comments I didn't like... I'm not in the mood right now. I think you'll get it as you learn how a bootsector does work. If not, ask again.

Best,
Frank

From my understanding of what I read before, the first few bytes of the first sector contain a jump instruction. This jump instruction jumps to a boot loader program, which starts in the first few bytes of the second sector. From then on there is no limit on how big that program can be. A boot loader can be any size. But I wondered to myself, "Is it possible to instead of using a jump instruction in the boot sector, put your whole program in the boot sector, and just make sure that the program is smaller than 512 bytes? I bet if I can keep the size of the program to under 512 bytes, it doesn't matter how many bytes of just data (not program code) come after this, as the act of copying data is distinct from executing code."

Offline z80a

  • Jr. Member
  • *
  • Posts: 20
Re: Some questions about 16bit DOS programming
« Reply #18 on: March 25, 2015, 12:59:41 AM »
The boot sector contains the whole MBR program & partition table, terminated by a 55 AA hex. The jump is only a leap of a few bytes. The MBR boot code will make a copy of itself, then jump to that new location at what would be its next instruction. It will then determine what partition is marked as "bootable" and load that bootstrap program into memory, typically where it previously was. The partition table is at the end of the MBR and contains four 16 byte entries (I'm speaking original partition table format), the entry with the first byte set as 80h is the boot partition. Using BIOS int 13h, that partitions boot record (first sector of that partition) will then be loaded and MBR will JMP to its first byte.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2359
  • Country: us
Re: Some questions about 16bit DOS programming
« Reply #19 on: March 25, 2015, 01:23:18 AM »
Well, that's almost right. The first few bytes of the first sector "should" contain a jump, but not to the second sector. (incidentally - unlike everything else in the known universe, sector numbers start at one, not zero) Only the first sector is going to be loaded by the BIOS. The only sensible thing for that code to do is to load something else. Often, this is a "second stage bootloader", often written to sector 2... and as many more sectors as you need. There are I think 64(?) "reserved" sectors that are free to use. After that comes directories and the FAT and stuff. Since you're not worried about that stuff at the moment, you can probably use the whole disk. But it will have to be loaded by code in the first sector - the BIOS won't do it, and I doubt if your VM will (but who knows what MS might do - won't hurt to try it).

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 100
Re: Some questions about 16bit DOS programming
« Reply #20 on: March 25, 2015, 02:32:18 AM »
Well, that's almost right. The first few bytes of the first sector "should" contain a jump, but not to the second sector. (incidentally - unlike everything else in the known universe, sector numbers start at one, not zero) Only the first sector is going to be loaded by the BIOS. The only sensible thing for that code to do is to load something else. Often, this is a "second stage bootloader", often written to sector 2... and as many more sectors as you need. There are I think 64(?) "reserved" sectors that are free to use. After that comes directories and the FAT and stuff. Since you're not worried about that stuff at the moment, you can probably use the whole disk. But it will have to be loaded by code in the first sector - the BIOS won't do it, and I doubt if your VM will (but who knows what MS might do - won't hurt to try it).

Best,
Frank

Since the BIOS doesn't know about the rest of the space on my disk, but my program DOES know about it. All my BIOS needs to do is execute my program. All the MOV statements or MOVSB statements in my program DO know about the rest of the space on the disk, because they are being executed by my program, not by the BIOS. At least I think that is correct.

Offline z80a

  • Jr. Member
  • *
  • Posts: 20
Re: Some questions about 16bit DOS programming
« Reply #21 on: March 25, 2015, 02:52:49 AM »
I'm assuming your not messing with your hard drives boot record, but a floppy or USB stick. I further assume you have created a bitmap memory image of what your trying to display, so that it can be directly loaded into video memory with proper video mode enabled.
Why not write your program to use BIOS int 13h to read sectors. Use Unix 'dd' (there's a Windows version), place your boot program in first sector and again use 'dd' to write your bitmap to the sectors you have your boot program reading.

With BIOS int 13h you set ES:BX to transfer location, AL will be number of sectors. In other words read sectors directly to video memory. Obviously ES will be set to A000h.

Offline ben321

  • Full Member
  • **
  • Posts: 100
Re: Some questions about 16bit DOS programming
« Reply #22 on: March 25, 2015, 04:55:22 AM »
I'm assuming your not messing with your hard drives boot record, but a floppy or USB stick. I further assume you have created a bitmap memory image of what your trying to display, so that it can be directly loaded into video memory with proper video mode enabled.
Why not write your program to use BIOS int 13h to read sectors. Use Unix 'dd' (there's a Windows version), place your boot program in first sector and again use 'dd' to write your bitmap to the sectors you have your boot program reading.

With BIOS int 13h you set ES:BX to transfer location, AL will be number of sectors. In other words read sectors directly to video memory. Obviously ES will be set to A000h.

Currently ES:DI is the receiving end. DS:SI is the source. CX is the number of bytes to read.

First thing I do is set ES segment to the video memory for VGA like this.
Code: [Select]
MOV AX,0xA000
MOV ES,AX
Then set the source and destinations indexes, and the byte count to transfer like this.
Code: [Select]
MOV SI,ImageData
MOV DI,0x0000
MOV CX,64000
ImageData is the name of the label that immediately precedes the image data.

To perform the transfer I do this.
Code: [Select]
REP MOVSB

I don't know why you are mentioning the BX register at all. ES:BX doesn't make sense, because transfers performed by MOVSB use DI as the destination pointer and SI as the source pointer, and using DS as the source segment and ES as the destination segment. So DS:SI is the source, and ES:DI is the destination. MOVSB doesn't use BX at all. I'm not sure what you are getting at with your suggestion, unless you are telling me that there's another way to do this transfer than to use REP MOVSB. BX is just like AX and DX. It's an extra space to put numbers that you are working with, as far as I know. It doesn't have any special use.
« Last Edit: March 25, 2015, 05:19:12 AM by ben321 »

Offline z80a

  • Jr. Member
  • *
  • Posts: 20
Re: Some questions about 16bit DOS programming
« Reply #23 on: March 25, 2015, 05:15:35 AM »
Reference for you:    http://en.wikipedia.org/wiki/INT_13H

If you look at function 02h (read sectors), you'll note that ES:BX points to your disk buffer area. I'm suggesting using your video area and directly reading sectors into it, hence no need for MOVSB.


Offline ben321

  • Full Member
  • **
  • Posts: 100
Re: Some questions about 16bit DOS programming
« Reply #24 on: March 25, 2015, 05:22:44 AM »
Reference for you:    http://en.wikipedia.org/wiki/INT_13H

If you look at function 02h (read sectors), you'll note that ES:BX points to your disk buffer area. I'm suggesting using your video area and directly reading sectors into it, hence no need for MOVSB.

There's absolutely no guaranty that my image data will start on a sector boundary. My image data's first byte is the very next byte after the last byte of code. The length of the code is determined by how big the opcodes are and how big parameters are. There's no way to make sure that my image data will start on a sector boundary. So using a command that transfers sectors will almost certainly NOT load the entire image.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2359
  • Country: us
Re: Some questions about 16bit DOS programming
« Reply #25 on: March 25, 2015, 08:04:27 AM »
Since a sector is the only unit you can transfer to or from a disk, you may have a problem finding an alternative. You can easily pad your file so your image data starts on a sector boundary - might be easier, but you don't have to. But I think you are going to have to load some more sectors (unless your image is pretty small). 125 of 'em, I figure, if you want the whole 64000 screenful.

Here's the Ralf Brown reference:

http://www.ctyme.com/intr/rb-0607.htm

Or maybe this one would work:

http://www.ctyme.com/intr/rb-0708.htm

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 100
Re: Some questions about 16bit DOS programming
« Reply #26 on: March 27, 2015, 02:30:21 AM »
Since a sector is the only unit you can transfer to or from a disk, you may have a problem finding an alternative. You can easily pad your file so your image data starts on a sector boundary - might be easier, but you don't have to. But I think you are going to have to load some more sectors (unless your image is pretty small). 125 of 'em, I figure, if you want the whole 64000 screenful.

Here's the Ralf Brown reference:

http://www.ctyme.com/intr/rb-0607.htm

Or maybe this one would work:

http://www.ctyme.com/intr/rb-0708.htm

Best,
Frank

I was depending on the content of the program containing this data itself. No need to have the extra data outside the executable COM file on the disk, because it would be a part of the file. I'm finding COM files are easier to work with than boot sectors, because I've never gotten that to work correctly (it can't seem to find the picture data past the end of the executable code when I use MOVSB to read the image bytes off of the disk image).

However I have run into a problem with COM files too. It works great with just one picture. However my plan was to make a more advance program and to have multiple pictures (test patterns in my case) in the files test.com and switch between pictures at the press of a key. But this has run into problems. Apparently the computer (in this case a virtual computer in Microsoft Virtual PC) gives the error "Program too big to fit in memory". Just how big can a COM file be, before it generates this error?
« Last Edit: March 27, 2015, 02:31:55 AM by ben321 »

Offline z80a

  • Jr. Member
  • *
  • Posts: 20
Re: Some questions about 16bit DOS programming
« Reply #27 on: March 27, 2015, 03:17:14 AM »
DOS .COM files by definition are 64K. This is because all segment registers are set to identical values at program load and execute.  If your not trying to create a boot (MBR) program, but instead are creating a .COM program, then you have all DOS calls (INT 21h & company) available to you. This means you can open files, no need to embed in executable.