flat assembler
Message board for the users of flat assembler.

Index > OS Construction > executing programs

Author
Thread Post new topic Reply to topic
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 16 Sep 2008, 01:59
Hi,

I'm trying to write a real mode os,I've finished FAT12 driver read/write.
and now I want to write some DOS ints,I know how to do that and INTs
are not my problem,the problem is in executing programs,I'm confused
about this,would some body please explain to me how to execute a program...
so my problem is that I don't know what to do after loading the program to the memory?
also is there a specific memory address the program should be loaded
into it?

Thanx.
Post 16 Sep 2008, 01:59
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 16 Sep 2008, 02:15
> I don't know what to do after loading the program to the memory?

Start it. Idea

Code:
jmp far seg:off
    


Code:
; place far return address on the stack if you want to return with RET
; AX has our segment address
pushw ax ; seg
xor   ax,ax
push  ax ; off
retfw
    


> also is there a specific memory address the program should be loaded
into it?

NO, anywhere where it's free, preferably 16-bytes aligned (so your "off" can be 0 as above).

BTW, if you are loading DOS COM's, your "off" and org must be $0100, not 0, also you must supply far return address on the stack, and support INT $20 and int $21/AH=$4C.
Post 16 Sep 2008, 02:15
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 16 Sep 2008, 04:06
hmm...
here's my code:
Code:
intialize:                          ;intializing interrupts table
       push  ds                            
        cli                             ;ints off                                
   mov word [es:21*4], int_21  ;move the offset 
   mov word [es:21*4+2], cs    ;move the segment into the interrupt table
  sti                             ;ints on
        pop   ds                        
        ret
int_21:                                      ;get input from the user
    xor     ah,ah                   ;al contains the char
       int     16h                     ;print out the char
 call    putc
        iret
    

I know I did't discuss the service number (ah value),just for simplicity
as this is the only int tell now in my os


I load the program at [es:0x200]
Code:
        mov     ax,es
        pushw   ax    ;seg 
        xor     ax,ax 
        mov     ax,0x200
        push    ax       ;off
        jmp far [es:0x200] 
        retfw      


would you please tell what I'm doing wrong here?

Thanx.
Post 16 Sep 2008, 04:06
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1905
DOS386 16 Sep 2008, 04:48
There are multiple ways how to start your application:

1. CALL FAR (pushes return far
address, RETFW will work to
terminate / return)
2. JMP FAR
3. RETFW

So you must use just __ONE__ of
them, and for 2 and 3 manually
push a far return address
__OR__ use an INT to terminate.

Also ES must be 0 when used for
writing
into the IVT, but non-ZERO and
sufficiently high for your
es:$0200 address.
Post 16 Sep 2008, 04:48
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 16 Sep 2008, 15:02
You should take a look at MiniDos http://board.flatassembler.net/topic.php?t=5275&start=0
As for load code example
Code:
    

The above will run a com or mz exe .
Post 16 Sep 2008, 15:02
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4354
Location: Now
edfed 16 Sep 2008, 16:56
very cool job dex.
load exe is my nightmare.

then i only load com using my own version of PSP.
Code:
;this is the file coordinates
file:
        db 2,81h       ;read on D:/
        dw 128         ;128 sectors
        dd 0ffff8844h  ;from C=0ffffh, H=88h, S=44h
        dd 1000h:0100h ;at 1000h:0100h
        dd 0           ;drive geometry, in CCCCHHSS, updated each drive operation on the item.
    

it is loaded in memory @ segment:0
Code:
        ... 
        mov si,file
        mov ax,[si+disk.seg]
        mov es,ax
        xor bx,bx
        mov cl,psp.end-psp
        mov di,psp
@@:
        mov ax,[di+bx]
        mov [es:bx],ax
        add bx,2
        dec cl
        jne @b
; after, the .com file is loaded using disk function.
        mov [si+disk.drv],dl
        call disk
; simply relocate the offset in the far pointer pointed to by si+disk.off
; then, it will call the far address [segment:offset]
        mov word [si+disk.off],0
; it will be called as a far address, @ segment:offset
 
       call far dword[si+disk.off]
; reset the offset with 100h value if we continue to use this object as org100h.     
       mov word [si+disk.off],100h
        ...
    


no need of org for this simple code, but shall be orged at 0 if it uses relative addressing
Code:
psp:
        push cs
        pop ds
        mov ax,100h
; and it will just call the near address, 100h
        call ax
;then, to quit, only a simple ret is needed,
;it is to the psp  to do the retf, not the application of course.
        retf
.end:

;and building an advanced PSP is not a pb.
align 100h

    


this comloader method is interresting, it permits to have the minimal .com program size = 1 byte.
Code:
org 100h
ret
    
Post 16 Sep 2008, 16:56
View user's profile Send private message Visit poster's website Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 18 Sep 2008, 04:43
right now I'm very confused,the only thing I'm sure of it is
cs = ds = es = ss = 50h, sp = 0, ip = 100h
but nothing else,would you please guys explain stuff to me step by step.

@Dex:
in the example you post,where did the program was loaded?
I load the program at es:0x200

Also would you please explain this to me:
Code:
mov     dl, [cs:bsDriveNumber]  ; let program know boot drive 
        mov     dh, 0xff                ; let DexOS know it booted from its bootloader 
    


Thanx.
Post 18 Sep 2008, 04:43
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 18 Sep 2008, 15:28
Ok here goes, when the above code says load address 60h the real address is 600h ( because of the realmode address are make up of seg and offset.
Now 600h is dec 1536

Now how a com file is load is in this case, it's load to 60h (real 600h ), then because of the ORG 100h that all com file have, we sub 10h (real 100h) off the 60h (real 600h) and set cs = ds = es = ss to 50h (real 500h) then es is push (=50h real 500h) and 100h is push for offset together the address = 60h (real 600h).
So a com file is load with a blank space before it, 100h in size eg:
***50h*** ; <cs = ds = es = ss (real address 500h
***60h*** ;< this is the load address (real address 600h)

Next when a com file is loaded it should have DL filled with the boot drive, in the above example
the var [bsDriveNumber] containeds the boot drive eg: 0 = A:, 80h = C: etc.
The other part is for DexOS, as i need to know if it booting from Dos or the bootloader.
I hope this helps as i am not good at explanions.
Post 18 Sep 2008, 15:28
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 19 Sep 2008, 04:13
Thank you Dex for your help,

so I should load my program at 50:100,is that right?
I tried this but it's not working,here's my code:

Code:
        mov     cx,1                    ;read one sector
        mov     bx,50                   
        mov     es,bx
        mov   bx,[es:0x100]           ;buffer for loaded file
        call    read_sectors            ;invoke BIOS
                    
        mov     ax, 60h
        mov     es, ax

        cli                             ; for stack adjustments
        mov     ax, es
        sub     ax, 10h                 ; "org 100h" stuff 
        mov     es, ax
        mov     ds, ax
        mov     ss, ax
        xor     sp, sp
        push    es
        push    word 100h
        mov     dl, 0
        sti
        retf
        pop     ax es    

every time I run the program my kernel just reloaded.

Thanx.
Post 19 Sep 2008, 04:13
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 19 Sep 2008, 15:18
You have put 50 instead of 50h
And i do not know how your read function is written, but normaly it users es:bx
So you would use something like this:
Code:
mov ax,60h
mov es,ax
xor  bx,bx
    

Before calling function.
Post 19 Sep 2008, 15:18
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 20 Sep 2008, 02:17
Hi,

you are right Dex the buffer is at es:bx,usuallly when I use
the function read_sectors,I use this combination:
Code:
mov bx,[es:0x100]
    

I tried what you adviced me but unfortunatelly my os just freezed,
so here's what I got:
code to load and execute
Code:
        mov     cx,1                    ;read one sector
        mov     bx,60h 
        mov     es,bx 
        xor     bx,bx                  ;buffer for loaded file(es=60h,bx=00)
        call    read_sectors           ;invoke BIOS
                    
        mov     ax, 60h
        mov     es, ax

        cli                             ; for stack adjustments
        mov     ax, es
        sub     ax, 10h                 ; "org 100h" stuff 
        mov     es, ax
        mov     ds, ax
        mov     ss, ax
        xor     sp, sp
        push    es
        push    word 100h
        mov     dl, 0
        sti
        retf
        pop     ax es
    


for intializing the interrupt table:
Code:
intialize:
 push  ds                            
        cli                             ;ins off                                
    mov word [es:21*4], int_21  ;move the offset 
   mov word [es:21*4+2], cs    ;move the segment into the interrupt table
  sti                             ;ints on
        pop   ds                        
        ret
    


Also:
Code:
int_21:                                   ;prints a single char from al
      call    putc
        iret
    


and here's my prog:
Code:
org      100h
mov     al,'m'
int       21h
    


Thank you for your help.
Post 20 Sep 2008, 02:17
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 20 Sep 2008, 15:55
First try these
Code:
Installints:
       push  ds                            ; Save DS
       cli                                 ; Turn off int's
       xor   ax,ax                         
        mov   ds,ax                         ; 0 DS
  mov   word [ds:21h*4],int21     ; load int vecter with int21h address
   mov   word [ds:21h*4+2],cs      ; + CS
  sti                                 ; Turn on int's
        pop   ds                            ; restore DS
    ret                                 ; Return
    

And
Code:
org      100h
mov     al,'m'
int       21h 
jmp $
    

As first you need to make sure ds or es is zero for the int vector and as theres no return, you best just loop for now at end of com file code.
If they do not work, post your read floppy function.
Post 20 Sep 2008, 15:55
View user's profile Send private message Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 20 Sep 2008, 22:46
Hi,

It didn't work,it suppose to print 'm',but unfortunatelly ,it didn't.
it just freezed .
here's my read_sectors:

Code:
read_sectors:
    push    di
  @main:
        mov     di,5
  @sectorloop:
        push    ax bx cx dx
        call    lbachs
        mov     ah, 0x02                    ;BIOS read sector
        mov     al, 0x01                    ;read one sector
        mov     ch, BYTE [track]            ;track
        mov     cl, BYTE [sector]           ;sector
        mov     dh, BYTE [head]             ;head
        mov     dl, 0                       ;drive
        int     0x13                        ;invoke BIOS
        jnc     @success
        xor     ax,ax
        int     0x13
        dec     di
        pop     dx cx bx ax
        jnz     @sectorloop
        int     0x18
@success:
        pop     dx cx bx ax
        add     bx,0x200                    ;add 512 bytes to buffer
        inc     ax
        loop    @main
      pop     di
        ret
    

and lbachs:
Code:
lbachs:
        push    dx bx ax cx           ;Save the value in dx
        xor     dx,dx                  ;Zero dx
        mov     bx, 18              ;Move into place STP (LBA all ready in place)
        div     bx                     ;Make the divide (ax/bx -> ax,dx)
        inc     dx                      ;Add one to the remainder (sector value)
        push    dx                  ;Save the sector value on the stack

        xor     dx,dx                        ;Zero dx
        mov     bx, 2               ;Move NumHeads into place (NumTracks all ready in place)
        div     bx                  ;Make the divide (ax/bx -> ax,dx)

        mov     cx,ax                       ;Move ax to cx (Cylinder)
        mov     bx,dx                      ;Move dx to bx (Head)
        pop     ax                     ;Take the last value entered on the stack off.
                                      ;It doesn't need to go into the same register.                                 ; Restore dx, just in case something important was                                      ; originally in there before running this.
        and       al,11111111b            ;make some bitwise operations
        mov     [sector],al             ;tostore the results in byte variables 
        and bl,11111111b
        mov     [head],bl 
        and       cl,11111111b
        mov    [track],cl 
        pop     cx ax bx dx 
        ret
    

sector,head and track are defined as bytes,
the thing is I'm pretty sure of this functions,becuase I wrote FAT12
driver read/write and it works fine.

an example:
Let's Assume I want to print the folders/files name from the first sector
in the root directory,here's what I do:
Code:
       mov     bx,[es:0x400]           ;the buffer
     xor     ax,ax                   ;zero ax
        mov     cx,ax                   ;zero cx
        mov     dx,ax                   ;zero dx
        mov     ax,19                   ;first sector of the root directory
        mov     cx,1                    ;read one sector                  
        call    read_sectors     
  call    printbuffer
    

Code:
;-----------------------------------------------;
; di points to the buffer                       ;
; bx points to the current char                 ;
; dx counts the length of the file name         ;
;-----------------------------------------------;
printbuffer:
        xor     ax,ax                   ;zero ax
        mov     bx,ax                   ;zero bx
        mov     dx,ax                   ;zero dx
        mov     si,ax                   ;zero si
        mov     di,ax                   ;zero di
        mov     di,[es:0x400]           ;di points to the buffer
        mov     cx,16                   ;number of root directory entries
  @loop: 
        test    byte[di+0x0b],1 shl 3   ;is it a volume label? 
        jnz     del                     ;don't print it 
        cmp     byte [di],0xE5          ;is it deleted file?
        je      del                     ;yes, don't print it
        cmp     byte [di],0x00          ;is this the end of files/directories?
        je      quit                    ;yes,quit
    no:                                 ;no...
        push    cx                      ;start printing the names
        mov     cx,11
        call    printname
        pop     cx

        add     di,21                   ;go to the next entry
        xor     bx,bx                   ;make bx zero
        xor     dx,dx                   ;make dx zero
        jmp     again                   ;continue printing!
     del:
        add     di,32                          
     again:   
        loop    @loop                   ;continue printing!                      
quit:
        ret       
    


I think the problem is in the buffer address(I'm not sure).
Thank you very much for your help.
Post 20 Sep 2008, 22:46
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville 21 Sep 2008, 03:50
If Dex doesn't lose his patience with you quite soon, then he must be a saint! Wink

My advice is that you should think twice about doing ASM, and especially about trying to write an OS with your present level of knowledge. You can not learn this way (by asking disjointed questions one by one on this board) - you obviously need to take a properly structured course, attend regularly, and learn methodically, step by step, following and understanding all the examples given. Until that happens I honestly feel you are likely to become even more confused and many of us will become more frustrated, including you

More specifically:
Writing an even simple OS requires some structure which you dont have. Displaying a single char on the screen and then allowing it to wander into neverland or looping forever is not a good idea. Very hard to test!

Why is your Boot & Exec code freezing?
1. Its difficult to tell if you've set everything up correctly e.g. the IVT entry for INT_21, your INT_21 ISR, the bootsector itself ....
2. You have set the stack to 50h:0h which means it will extend downwards into the BIOS data area. How many bytes does your subsequent INT call put on the stack? ANS: 6
3. CS:IP on booting is usually 0:7C00h but is 7C0h:0 with some BIOS's
Do you know where CS really is?

Also:
POPs after the RETF won't be executed...
What is the purpose of AND AL,11111111h etc in LBACHS? (rhetorical Q!)

Good luck! I've said what I think needs to be said. I see you've been on this board for nearly 2 years (while I've only been here for 2 months). Please don't think I'm trying to be mean to you - just because I once criticised your putc subroutine which calls itself. I sincerely believe you should heed my blunt, but heart-felt advice Smile

_________________
FAMOS - the first memory operating system
Post 21 Sep 2008, 03:50
View user's profile Send private message Visit poster's website Reply with quote
abuashraf



Joined: 11 Nov 2006
Posts: 88
abuashraf 21 Sep 2008, 04:45
Quote:
If Dex doesn't lose his patience with you quite soon, then he must be a saint!


Dex was very helpfull,and I learnt alot from him.

Quote:
Writing an even simple OS requires some structure which you dont have. Displaying a single char on the screen and then allowing it to wander into neverland or looping forever is not a good idea. Very hard to test!

I think you are missing the point here,I'm trying to add support
to .com progs in my os,so for the simplicity this program
is going to print a single char.

Quote:
Good luck! I've said what I think needs to be said. I see you've been on this board for nearly 2 years (while I've only been here for 2 months). Please don't think I'm trying to be mean to you - just because I once criticised your putc subroutine which calls itself. I sincerely believe you should heed my blunt, but heart-felt advice

Don't worry about that,I know that your intentions are good.
Also I've fixed that procedure.

Maybe I'm here for about two years,but I started coding and spending some time with asm,in the middel of this summer,so it's about two mounthes,Also in this two mounthes I wrote a real mode os
and I learnt alot from this experience.
they only thing left todo in this real mode os is loading and executing
.com prog and sure implementing some Dos INTs(the famous).
Post 21 Sep 2008, 04:45
View user's profile Send private message Reply with quote
Dex4u



Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 21 Sep 2008, 18:29
One thing, which i have pointed out before is your addressing is wrong for your read sector function, you pointing to whats in the address, not the address.
Try using this in your com file code
Code:
        pusha
     push  es
        mov   ax, 0B800h
        mov   es, ax
        mov   byte [es:0], "M"
        pop   es
    popa
    

In stead of your int 21h, also in your code add something like this untill you find the problem
Code:
        pusha
     push  es
        mov   ax, 0xB800
        mov   es, ax
        mov   byte [es:0], "1"
        pop   es
    popa
;some code here
        pusha
    push  es
        mov   ax, 0xB800
        mov   es, ax
        mov   byte [es:0], "2"
        pop   es
    popa
;some code here
        pusha
    push  es
        mov   ax, 0xB800
        mov   es, ax
        mov   byte [es:0], "3"
        pop   es
    popa
;some code here
        pusha
    push  es
        mov   ax, 0xB800
        mov   es, ax
        mov   byte [es:0], "4"
        pop   es
    popa
;some code here
; more here etc
    

And see what number you get too, before it crashs.
Post 21 Sep 2008, 18:29
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.