flat assembler
Message board for the users of flat assembler.
Index
> OS Construction > loading program (real mode) |
Author |
|
bitRAKE 26 Mar 2009, 04:12
Nothing posted here seems incorrect.
Where does it go wrong? The CALL to $2000:$0100 does not happen? |
|||
26 Mar 2009, 04:12 |
|
abuashraf 26 Mar 2009, 13:37
humm...
when I load my programs at the same segment of my kernel, I just call like this: Code: call 0x100 and every ting works well. my kernel is loaded at segment 0x1000:0x0000,and I want to load programs at 0x2000:0x0100 when I execute the previous code I get garbage,what do I need to change?do I need to change the CS to 0x2000? |
|||
26 Mar 2009, 13:37 |
|
DOS386 26 Mar 2009, 14:28
> when I load my programs at the same segment
What address inside ? > of my kernel, I just call like this: > call 0x100 How big is your "kernel" ? > do I need to change the CS to 0x2000? YES. You need a far call and far return. > call 0x2000:0x0100 ;jump to the program But this seems to do the job. But you seem to load at $2000:0 and start at $2000:$0100 ... do your executables begin with 256 empty Bytes ? |
|||
26 Mar 2009, 14:28 |
|
edfed 26 Mar 2009, 17:10
cool tip:
instead of manipulating immediate values for far addresses, use a single dword to store that address Code: address dd 1234h:5678h ; all theses three lines output the same offset = 0 segment = 2 ; address dw 5678h,1234h ; address dd 12345678h ... mov word[address+offset],100h mov word[address+segment],1000h mov eax,address call far dword[eax] jmp far dword[eax] ... this have the advantage to manipulate a structure about .com loading in another segment: the PSP (the memory between cs:0 and cs:0ffh) is there for system interfacing. __1/ create the psp Code: psp dd 1000h:0 ____a/ copy this basic bloc of instructions at psp=[1000h:0] Code: org 0 ...; initialise registers mov ax,100h call ax ...; check error messages retf ; return to OS ... ____b/ create the features you want within the spare memory before 100h __2/ copy the .com program at psp=[1000h:0+100h] ______° the .com program should begin with this bloc of instructions: Code:
org 100h
______° the .com program should quit with this bloc of instructions: Code: ;mov ax,3 ; for msDOS ;int 10h ; for msDOS ret __3/ call the PSP Code: mov eax,psp call far dword[eax] |
|||
26 Mar 2009, 17:10 |
|
Dex4u 27 Mar 2009, 07:06
You need to set the reg before jumping to it eg:
Code: ImageLoadSeg equ 60h ;;;;;;;;;;;;;;;;;;; ;; Type checking ;; ;;;;;;;;;;;;;;;;;;; cli ; for stack adjustments mov ax, ImageLoadSeg mov es, ax cmp word [es:0], 5A4Dh ; "MZ" signature? je RelocateEXE ; yes, it's an EXE program ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Setup and Run COM program ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 jmp Run ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Relocate, setup and run EXE program ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RelocateEXE: mov ds, ax add ax, [ds:08h] ; ax = image base mov cx, [ds:06h] ; cx = reloc items mov bx, [ds:18h] ; bx = reloc table pointer jcxz RelocationDone ReloCycle: mov di, [ds:bx] ; di = item ofs mov dx, [ds:bx+2] ; dx = item seg (rel) add dx, ax ; dx = item seg (abs) push ds mov ds, dx ; ds = dx add [ds:di], ax ; fixup pop ds add bx, 4 ; point to next entry loop ReloCycle RelocationDone: mov bx, ax add bx, [ds:0Eh] mov ss, bx ; ss for EXE mov sp, [ds:10h] ; sp for EXE add ax, [ds:16h] ; cs push ax push word [ds:14h] ; ip Run: mov dl, [cs:bsDriveNumber] ; let program know boot drive mov dh, 0xff ; let DexOS know it booted from bootprog sti retf Example if ImageLoadSeg is 60h, than a com would be dl = boot drive number cs:ip = program entry point ss:sp = program stack (don't confuse with boot sector's stack) COM program defaults: cs = ds = es = ss = 50h, sp = 0, ip = 100h Also take a look at MiniDos |
|||
27 Mar 2009, 07:06 |
|
abuashraf 28 Mar 2009, 11:33
Hi,
Thank you guys for your help,now I can execute programs successfully ,but I still have a problem,so after finishing the execuion of the program I can't return to my os. The os sometimes reboot,and sometimes just freeze here's my code: Code: loadfile: mov ax,[cluster] call load_fat ;load fat table into memory mov ax,word [cluster] xor bx,bx load_file: push ax ;save cluster number sub ax,2 add ax,33 call lba_to_chs ;convert from LBA to CHS push ax es mov ax,0x2000 mov es,ax mov bx,[.offset] ;now load... mov ah,02 mov al,01 int 13h pop ax ;get cluster back call getcluster ;check for the next cluster cmp ax,0x0FF8 ;is it the end of the file? jae .end ;yes... add word [.offset],512 ;no,add 512 byte to the offset pop es ax jmp load_file ;continue .end: pop es ax call execute_program ret Code: execute_program: mov ax,0x2000 ;set regs to the adress of the loaded program mov ds,ax mov es,ax mov fs,ax mov gs,ax call 0x2000:0x0100 ;jump to the program .end: sti retf ;get cs/ip back from the stack mov ax,0x1000 ;set regs to the adress of the kernel mov ds,ax mov es,ax mov fs,ax mov gs,ax ret Please note that my kernel is loaded at 0x1000:0x0000 and it's less than 64k and programs are loaded at 0x2000:0x100 |
|||
28 Mar 2009, 11:33 |
|
revolution 28 Mar 2009, 11:57
What is the retf for? I think you don't need it.
BTW: You seem to be running your program on the kernel's stack. Your program can also corrupt your ret address on the stack. |
|||
28 Mar 2009, 11:57 |
|
abuashraf 28 Mar 2009, 13:06
Quote: What is the retf for? I think you don't need it. when I do call 0x2000:0x100 the current values of CS/IP are pushed onto the stack before executing at the new position. the retf will pops the return segment/offset from the stack into CS/IP and switches execution to that address. Quote: BTW: You seem to be running your program on the kernel's stack. Your program can also corrupt your ret address on the stack humm... in this case I need to make a stack for the programs, if so does it need to be in the same segment? I mean does it need to be in 0x2000 segment? Thanx. |
|||
28 Mar 2009, 13:06 |
|
revolution 28 Mar 2009, 13:24
abuashraf wrote:
abuashraf wrote:
|
|||
28 Mar 2009, 13:24 |
|
abuashraf 28 Mar 2009, 17:21
I've tried everything ,but nothing seems working,
I'm confused ,I satup a stack segment for the loaded programs,but It didn't work Code: execute_program: mov ax, 0x3000 mov ss, ax ;set stack segment and pointer mov sp, 0xF000 mov ax,0x2000 ;set regs to the adress of the loaded program mov ds,ax mov es,ax mov fs,ax mov gs,ax call 0x2000:0x0100 ;jump to the program .end: mov ax, 0 mov ss, ax ;get kernel stack back mov sp, 0xF000 mov ax,0x1000 ;set regs to the adress of the kernel mov ds,ax mov es,ax mov fs,ax mov gs,ax retf ;get cs/ip back from the stack would you please guide me, what's wrong with my code? thanx. |
|||
28 Mar 2009, 17:21 |
|
revolution 28 Mar 2009, 18:12
You can't use retf to return from execute_program because you called it with a near call, so the return must match with a retn. BUT, you are setting your stack to 0:f000 after the program returns (can I assume the program returns with retf? Since you called it with a far call.) so your original return address is most probably lost in some other part of memory.
You should save the position of the kernel stack SS and SP somewhere and then restore is again to the original values, then use a matching near return retn. Code: execute_program: ;save the kernal stack somewhere first mov [mySavedKernelStackSS],ss mov [mySavedKernelStackSP],sp ;save other kernel segments mov [mySavedKernelStackES],es mov [mySavedKernelStackFS],fs mov [mySavedKernelStackGS],gs mov ax, 0x3000 mov ss, ax ;set stack segment and pointer mov sp, 0xF000 ;can also make it 0x0000 mov ax,0x2000 ;set regs to the adress of the loaded program mov ds,ax mov es,ax mov fs,ax mov gs,ax call 0x2000:0x0100 ;call the program ;restore other kernel segments mov ax,0x1000 mov ds,ax mov es,[mySavedKernelStackES] mov fs,[mySavedKernelStackFS] mov gs,[mySavedKernelStackGS] ;restore the kernel stack mov ss,[mySavedKernelStackSS] mov sp,[mySavedKernelStackSP] retn ;a matching near return, can't use retf since it was called with a near call |
|||
28 Mar 2009, 18:12 |
|
edfed 29 Mar 2009, 11:32
i gave you the solution of this kind of stuff but nobody saw it.
the PSP is there to help you. the system is at a segment. the program is at another segment. the system will call the programm with a far call. and the program will return with a near ret. then, the psp is the bridge between the two. and permitt to pass parameters too. |
|||
29 Mar 2009, 11:32 |
|
abuashraf 29 Mar 2009, 17:31
Please guys be patient with me...
unfortunately It didn't work ,some programs just restart itself from the begining... I've been trying this for more than 6 hours. I'm testing my os using Bochs,so when I quit I took a look at bochsout.txt it says: Code: prefetch: EIP [00010000] > CS.limit [0000ffff] IRET: top 6 bytes of stack not within stack limits and here's the cpu registers: Code: CS:f000( 1e00| 0| 0) 000f0000 0000ffff 0 0 DS:0045( 0000| 0| 0) 00000450 0000ffff 0 0 SS:41c3( 0000| 0| 0) 00041c30 0000ffff 0 0 ES:2000( 0000| 0| 0) 00020000 0000ffff 0 0 FS:2000( 0000| 0| 0) 00020000 0000ffff 0 0 GS:2000( 0000| 0| 0) 00020000 0000ffff 0 0 EIP=0000ff53 (0000ff53) and here's my int 20h implementation (quit from the program): Code: int20: cli push cs pop bx mov ds,bx mov es,bx mov ss,bx xor sp,sp sti call _shell iret My kernel is loaded at 0x1000,and programs are loaded at 0x2000 so I think DS,SS,ES,FS,and gs should equal 0x2000 |
|||
29 Mar 2009, 17:31 |
|
revolution 29 Mar 2009, 17:38
You entered you app with call far so your app should return in kind with retf.
You can't mix your call/ret models because the stack will not be correct to get back the various registers. If you want to use an int function to return from your app then the int function must restore the stack to the same state as the the kernel left it and then do a retf to get back the to original code after the call to the app. |
|||
29 Mar 2009, 17:38 |
|
abuashraf 29 Mar 2009, 19:39
so in my int 20 function
I should do retf to get the CS/IP back from the stack then restore kernel segments and restore the kernel stack then return to my os,Am I right? if this is right,what do I need to do in the "execute_program" after the call? Thanx. |
|||
29 Mar 2009, 19:39 |
|
revolution 30 Mar 2009, 00:24
If your app does not properly preserve the stack then the int 20 function will have to do that. In your case above you have this:
Code: mov ax, 0x3000 mov ss, ax ;set stack segment and pointer mov sp, 0xF000 ;can also make it 0x0000 Code: call 0x2000:0x0100 ;call the program Code: int20: mov ax, 0x3000 mov ss, ax ;set stack segment and pointer mov sp, 0xEFFC retf |
|||
30 Mar 2009, 00:24 |
|
abuashraf 30 Mar 2009, 14:29
Hi,
I've changed some stuff,so now I start loading my kernel at 0x2000:0x000 and programs are loaded at 0x3000:0x0000 after this changes and after trying what you adviced me in the last reply now I'm able to successfuly quit of a simple "hello world" program,and also another game called pitman.com. but there are other games that I couldn't get out successfuly. In the past when I loaded my kernel and programs at the same segment I was able to get out of this games without any troubles. so when I took a look at bochsout after trying the nonworking games it gave me: Code: 00266478000i[CPU0 ] | CS:3000( 1e00| 0| 0) 00030000 0000ffff 0 0 00266478000i[CPU0 ] | DS:3000( 0000| 0| 0) 00030000 0000ffff 0 0 00266478000i[CPU0 ] | SS:4000( 0000| 0| 0) 00040000 0000ffff 0 0 00266478000i[CPU0 ] | ES:3000( 0000| 0| 0) 00030000 0000ffff 0 0 00266478000i[CPU0 ] | FS:3000( 0000| 0| 0) 00030000 0000ffff 0 0 00266478000i[CPU0 ] | GS:3000( 0000| 0| 0) 00030000 0000ffff 0 0 00266478000i[CPU0 ] | EIP=00000c15 (00000c15) 00266478000i[CPU0 ] | CR0=0x00000010 CR1=0 CR2=0x00000000 00266478000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 I think this means that the cpu couldn't get its regs right values back. So what do you think?what can I else do? |
|||
30 Mar 2009, 14:29 |
|
GhostXoPCorp 04 Jun 2009, 21:38
this all makes my os seem simple
|
|||
04 Jun 2009, 21:38 |
|
DOS386 05 Jun 2009, 04:27
abuashraf wrote: I'm writing a real mode os,till now I'm able to load and execute .com programs,I load my kernel and programs at the same segment DOS compatible ??? Quote: I've changed some stuff,so now I start loading my kernel at 0x2000:0x000 and programs are loaded at 0x3000:0x0000 after this changes and after trying what you adviced me in the last reply now I'm able to successfuly quit of a simple "hello world" program,and also another game called pitman.com. but there are other games that I couldn't get out successfuly. In the past when I loaded my kernel and programs at the same segment I was able to get out of this games without any troubles. What are the applications ? DOS COM ones ? You can exit a DOS COM by a near RET or INT $20 or INT $21 / AH=$4C ... also, DOS COM expects org $0100 while DOS MZ EXE expects org 0, both COM and MZ EXE expect to be preceded by a PSP serving various purposes, among others exiting a COM with a near RET |
|||
05 Jun 2009, 04:27 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.