2

I have a problem with some code. It's a part of my own OS that I want to build in the future and share on SourceForge. I have two assembly files:

  1. gdos.asm, the kernel. And...
  2. vga.asm, my own VGA driver.

Everything works correctly in DOSBox.
But when I run it on normal MS-DOS on my external drive, it's causing this error:

Memory allocation error:
Failed load COMMAND.COM. System halted

This problem may be related to the code where I allocate extra memory to the program by resizing it. The complete source code is:

First file: GDOS.ASM:

format MZ
stack 4096
entry GDOS_MAINSEG:GDOS_KERNEL_START

segment GDOS_MAINSEG
        GDOS_KERNEL_START: ; Punkt startowy jĄdra / Kernel start point
                        push cs
                        pop ds

                        push cs
                        pop es

                        mov ax,GDOS_KERNEL_END ;Autoalokacja do konkretnego rozmiaru / Autoallocation for concrete size
                        shr ax,4
                        inc ax
                        init: ;Inicjujemy GDOS
                        mov bx,ax
                        mov ah,0x4a
                        int 0x21

                        mov dx,DrvString0
                        call far GDOS_MAINSEG:gdosLoadDriverDOS

                        call far GDOS_MAINSEG:gdosSetModeByID


                        mov ax,0x4c00
                        int 0x21

                        GDOS_KERNEL_DATA:
                                DrvString0 : db 'VGA.BIN',0 ;Nazwa pliku dla sterownika VGA / Filename for VGA driver

                                GraphicsDriver: dw 0x0

                                g3:
                                dw 0,0
                                dw 0,0

                                DriverDeletionBuffer: TIMES 16 db 0
                                RecommendedDriverPosition: db 0

                        GDOS_KERNEL_FUNC:
                                gdosLoadDriverDOS: ;Funkcja adujĄca sterownik za pomocĄ DOS-a / Function loading driver with DOS
                                        push ds
                                        push es
                                        mov ax,0x3d00
                                        mov cl,0x0
                                        int 0x21
                                        jc end_gdosLoadDriverDOS
                                        mov si,ax ;Zapisz uchwyt / Save handle
                                        mov ah,0x48
                                        mov bx,1
                                        int 0x21
                                        jc end_gdosLoadDriverDOS
                                        mov es,ax
                                        mov ds,ax
                                        mov ah,0x3f
                                        mov cx,16
                                        mov bx,si
                                        mov dx,0
                                        int 0x21
                                        jc end_gdosLoadDriverDOS
                                        mov ah,0x42
                                        mov al,0x00
                                        mov cx,0
                                        mov dx,0
                                        int 0x21
                                        jc end_gdosLoadDriverDOS
                                        mov bx,[0x2]
                                        mov cx,bx
                                        shr bx,4
                                        inc bx
                                        mov ah,0x4a
                                        int 0x21
                                        mov bx,si
                                        mov dx,0
                                        mov ah,0x3f
                                        int 0x21
                                        mov [0x2],es
                                        mov bp,0x0
                                        call far [es:bp]
                                        push cs
                                        pop ds
                                        mov bp,g3
                                        mov [bp+2],es


                                        end_gdosLoadDriverDOS:
                                        pop es
                                        pop ds
                                        retf

                                gdosSetModeByID:
                                        push es
                                        push ds

                                        push cs
                                        pop ds

                                        mov bp,g3
                                        mov ax,[GraphicsDriver]
                                        shl ax,2
                                        add bp,ax

                                        mov di,[bp+2]
                                        mov es,di

                                        mov di,[es:11]

                                        sub sp,4
                                        mov bp,sp
                                        mov [ss:bp],di
                                        mov [ss:bp+2],es
                                        call far [ss:bp]

                                        add sp,4
                                        pop ds
                                        pop es
                                        retf

        GDOS_KERNEL_END:

Second file: VGA.ASM

    GDOS_DRIVER_START:
        GDOS_SECTION_DRIVER_HEADER:
                gEntry: dw vgaEntry ;Punkt wejścia sterownika / Driver entry
                gDriverSize: dw GDOS_DRIVER_END ;Rozmiar sterownika w bajtach  / Driver size in bytes
                gDriverType: db 1 ;0x1 - Sterownik grafiki / 0x1 - Graphics driver
                gPortsData: dw vgaPorts
                gMemData: dw vgaMem
                gShared: dw vgaShared ;Lista sterowników dla których zasoby są udostępnione
                gBasicFunc: dw vgaChangeModeID
                gBasicPtrs: dw vgaPtrs
        GDOS_SECTION_DRIVER_DATA:
                vgaIDString: db 'vga-drv$',0 ;Służy do wyszukiwania sterownika przez GDOS / It's for GDOS driver search
                vgaShared0: db 'svga-drv',0
                vgaEntry:
                        retf
                vgaPorts:
                db 0x1
                db 2 
                dw 0x3c8,0x3c9
                db 0x0
                vgaMem:
                db 0x1
                db 2
                dd 0x0000A000,0x0000BFFF
                db 0x0
                vgaShared:
                db 0x1
                dw vgaShared0
                db 0x0

                vgaPtrs:
                        dw vgaModes
                vgaModes:


                vgaFunc:
                dw vgaChangeModeID

                vgaMisc_Common db 0x63
                R_W256 db 0x00
                R_W320 db 0x00
                R_W360 db 0x04
                R_W376 db 0x04
                R_W400 db 0x04

                R_H200 db 0x00
                R_H224 db 0x80
                R_H240 db 0x80
                R_H256 db 0x80
                R_H270 db 0x80
                R_H300 db 0x80
                R_H360 db 0x00
                R_H400 db 0x00
                R_H480 db 0x80
                R_H564 db 0x80
                R_H600 db 0x80

                HOR_REGS db 0x0,0x1,0x2,0x3,0x4,0x5,0x13
                VER_REGS db 0x6,0x7,0x9,0x10,0x11,0x12,0x15,0x16

                W256: db 0x5f,0x3f,0x40,0x82,0x4a,0x9a,0x20


                vgaChangeModeID: ;TEST
                push ds
                push cs
                pop ds
                mov ah,9
                mov dx,vgaIDString
                int 0x21
                pop ds
                retf

GDOS_DRIVER_END:

To assemble the files into GDOS.EXE and VGA.BIN I use the commands:

fasm GDOS.ASM
fasm VGA.ASM

When the program is run I expect it to display the following and then exit back to the DOS prompt:

vga-drv

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
micheal007
  • 137
  • 9
  • 3
    There are a variety of things wrong with the code. If it happened to work in DOSBox it was by luck alone. The end of your program isn't actually `GDOS_KERNEL_END` . FASM places the stack after the CODE/DATA/BSS data. The segment just beyond the stack is the upper end of the program. The next big problem is the lack of error checking where it is actually needed. You should be checking the Carray Flag CF after the memory allocation routines. You may discover failures where you weren't expecting them – Michael Petch Jun 30 '19 at 17:08
  • You allocate space (using DOS allocate) to get 16 bytes and read the header of the driver in. That's okay but be aware, DOS will allocate it in any available free memory regions that has 16 bytes free. That could be before your program in memory where it may not resized. The problem is that after you figure out the file size by reading the driver header you resize the memory block so that you can read the entire driver in. The problem is that you may not be able to resize from the 16 byte region to something larger! If you had CF error checking on the resize you'd probably discover a failure – Michael Petch Jun 30 '19 at 17:12
  • What you can do is create a 16 byte buffer in your GDOS's data area that can read the header into. Then use DOS allocate function (rather than resize) to get the space you need. – Michael Petch Jun 30 '19 at 17:12
  • Another place you may get a failure is right near the beginning. When you do attempt to resize the program area you do it on the value of DS (which you set to CS clobbering DS's initial segment). The problem is that CS isn't actually the beginning of the program's memory segment that was allocated. That really starts in the segment with the 256 byte PSP that sits just below CS. When an EXE program starts DS and ES actually point to the PSP. That is the segment you should be resizing, not the segment CS points at. – Michael Petch Jun 30 '19 at 18:35
  • 1
    There are places in your code where you use [bp] but don't override the implicit SS with the proper data segment. I'd recommend using [bx] in places where you wants references to DS rather than SS. I'm curious if this revision of your code works: http://pastebin.com/bBw0R6kW . I've added rudimentary error checking and display an error message for debug purposes. You may not need all the error checking and you can remove what you don't need. I added them to aid debugging only. The program does not call into the driver if the driver can't be successfully opened and loaded into memory. – Michael Petch Jul 01 '19 at 03:52
  • The revised code also properly converts an offset to the nearest paragraph (16 byte boundary). Your way works, but if the offset your are converting to paragraphs is already 16 byte aligned you unnecessarily allocate an extra paragraph. Rather than divide the offset by 16 and add 1 as you do, you can add 15 (16-1) to the offset and then divide by 16 – Michael Petch Jul 01 '19 at 04:01
  • Please create a new question for your video driver issue. Answers are for answers only, not new questions. When you do create a new question make sure you show the code for GDOS.ASM and your VGA driver. – Michael Petch Jul 02 '19 at 19:47

0 Answers0