flat assembler
Message board for the users of flat assembler.

Index > DOS > Load code into memory

Thread Post new topic Reply to topic
Sebastian R.

Joined: 26 Oct 2006
Posts: 4
Sebastian R. 27 Oct 2006, 09:54
I would like to write a program that loads another .Com-file into memory and then executes this program.

I thought I could use a variable (TheCode db 4000 DUP (?)) to store the code and then jump to the code offset, but somehow it won't work. Has anyone a working example for me? (It is important to get the code into a variable, because I would like to encrypt/decrypt this code afterwards.)

Post 27 Oct 2006, 09:54
View user's profile Send private message Reply with quote
MaurĂ­cio Pezzotta

Joined: 19 Oct 2006
Posts: 6
MaurĂ­cio Pezzotta 27 Oct 2006, 10:05
I think that in a .com file you'd have to jump to the code offset+256, not just the offset.
Post 27 Oct 2006, 10:05
View user's profile Send private message Reply with quote
Sebastian R.

Joined: 26 Oct 2006
Posts: 4
Sebastian R. 27 Oct 2006, 10:14
Thanks, I am using the followin code.
  .model tiny
    ByteCode db 61440 DUP (?)
    Buffer db 0
    Filename db "TEST.COM", "$"
    hFile dw ?
  org 100h
    mov ah, 3Dh
    mov al, 0
    lea dx, Filename
    int 21h
    mov hFile, bx
      mov ah, 3Fh
      mov bx, hFile
      mov cx, 1
      lea dx, ByteCode
      int 21h
      cmp ax, 0h
      je GoOn
      jmp ReadCode
      lea dx, ByteCode+256
      jmp dx

    mov ah, 4ch
    int 21h
  end start

(still TASM syntax)

But it doesn't work. Any suggestions?
Post 27 Oct 2006, 10:14
View user's profile Send private message Reply with quote

Joined: 15 Sep 2006
Posts: 181
Goplat 27 Oct 2006, 16:48
Every byte you read will just overwrite the last one, since you always write to [ByteCode]. But even if you fixed that it would not work. A .COM program expects to start at offset 100h so you would have to do some funky segment munging to make that so. Moreover, all DOS programs need to have a PSP in the first 256 bytes of their memory, and setting one up manually would be annoying.

The easiest way to execute another program is with int 21/AH=4B. (You'll have to shrink your own program's memory block with int 21/AH=4A first.)
Post 27 Oct 2006, 16:48
View user's profile Send private message Reply with quote

Joined: 08 Feb 2005
Posts: 1601
Location: web
Dex4u 27 Oct 2006, 17:04
Here: is the code (tasm need converting)
;; COM file loader;; David Lindauer, March 25, 1997;;  This should run MOST com files, if not all of them.  The only;  especially tricky part is marking the newly allocated memory;  segments with an appropriate owner so that the memory will be;  released properly when the program exits.;;  Note: there are some aspects of DOS compatability I haven't taken;  care of here; for example the program name should show up right after;  the environment with a fully qualified path; and it should show up;  again right after the command line without the path.  I may have missed;  other stuff as well...;;        .model tiny        .386        .code        org 100hstart:        jmp go        db 0C4h         ; word aligning the stack;_____________________________________________________________________;; Internal stack;        dw      128 DUP ('?')tos:;_____________________________________________________________________;; Internal variables;query db        10,13,"Please enter name of file to execute: ",'$'response db     40,0,40 DUP (?);_____________________________________________________________________;; Failure comes here;errmsg db       10,13,"failed.",10,13,'$'failure:        push cs                 ; print a message if something fails        pop ds        mov dx,offset errmsg        mov ah,9        int 21h        mov ax,4c01h        int 21h;_____________________________________________________________________;; Prepare an empty environment.  COMMAND.COM copies the environment of; the parent to a new hunk of memory and throws some data in after it;; We just make an empty environment;prepare_env:        mov bx,1                ; need one paragraph        mov ah,48h        int 21h        jc failure        mov es,ax               ; Zero it out        sub di,di        sub ax,ax        mov cx,8        rep stosw        ret;_____________________________________________________________________;; Allocate all useable memory to our new prog; Actually not 100% compatible with what DOS does but close enough; for IBM PC computers.;allocate_allmem:        mov bx,-1               ; find out how much mem        mov ah,48h        int 21h        cmp bx,1000h            ; At least 64K?        jc failure        push bx                 ; Allocate it        mov ah,48h        int 21h         mov es,ax        pop bx                  ; returning size of block        jc failure        ret;_____________________________________________________________________;; Initialize the new PSP;; Note: this should handle most DOS .COM files.  Of course it; makes little sense to go to all this trouble if we aren't running DOS; programs Smile.   BTW this should let them run, but it may keep them from; important information such as command lines and environments;prepare_psp:        push ax                 ; start by zeroing it out        mov cx,128        sub ax,ax        sub di,di        rep stosw        pop ax        mov word ptr es:[2ch],ax        ; Pointer to our environment        mov word ptr es:[0],20cdh       ; null return to DOS        mov ax,es        add ax,bx        mov word ptr es:[2],ax          ; Next free block (usually A000)        mov byte ptr es:[5],9ah         ; CALLF;; Now we grab stuff from the original PSP.  Usually DOS initializes; this stuff with values out of the appropriate vectors but I got lazy...;        mov si,6                        ; vectors 21h-24h copy from old PSP        mov di,6        mov cx,8        rep movsw        mov ax,ds:[16h];; This next field would typically be set to point at itself or; the parent which did the spawning; I set it to the parent of; this loader program;        mov word ptr es:[16h],ax        ; Common parent        mov byte ptr es:[18h],1         ; Handle table        mov byte ptr es:[19h],1        mov byte ptr es:[1ah],1        mov byte ptr es:[1bh],0        mov byte ptr es:[1ch],2        mov di, 1dh                     ; blank out unused entries (handles)        mov al,0ffh                                                         mov cx,15        rep stosb        mov word ptr es:[32h],20        ; 20 handles available        mov word ptr es:[34h],18h       ; Point at handle table        mov word ptr es:[36h],ES        ;        mov dword ptr es:[38h],-1       ; reserved        mov word ptr es:[50h],21CDh     ; dummy DOS call        mov byte ptr es:[52h],0CBH;; The rest of this stuff has to be modified if you put in command line support;        mov di,5dh                      ; Now blank out the FCB file names        mov al,20h        mov cx,8        rep stosb        mov di,6dh        mov cx,8        rep stosb        mov word ptr es:[80h],0D00h     ; Indicate no command line        ret;_____________________________________________________________________;; Reclassify the memory for the PSP and ENV as being owned by the PSP; If we don't do this the memory may not get freed up... which typically; results in a lockup.;rename_arena:        push es        push es        mov ax,es:[2ch]        dec ax        mov es,ax        pop ax        mov es:[1],ax        dec ax        mov es,ax        pop ax        mov es:[1],ax        mov es,ax        ret;_____________________________________________________________________;; Program entry point;go:        mov sp,offset tos               ; Switch to internal stack;; This is the standard ASM prelude for freeing up memory the program; isn't using;        mov bx,offset eop               ; Free up unused memory        add bx,15        shr bx,4        mov ah,4ah        int 21h;; Everything up to here is to adjust for the fact we are already a com file;;; First we make the environment.  We are making an empty one but it should; get copied either from the master environment or from the parent's ; environment        call prepare_env                ; Memory initialize;; Allocate program memory.  We are going to allocate anything we can; get our hands on.  We HAVE to allocate this rather than just default; to the pre-allocated memory because some programs depend on the PSP; being at the beginning of an arena block;        push es        call allocate_allmem        pop ax;; Now initialize all relevant fields of the PSP;        call prepare_psp;; Retag the arena entries for the memory we have allocated so it will; be freed properly;        call rename_arena               ; rename the arena entries;; Put a prompt and get file name;        mov dx,offset query             ; Get the file name        mov ah,9        int 21h        mov dx,offset response        mov ah,10        int 21h        mov bh,0        mov bl,[response+1]        mov [bx+response+2],0;; Read in the file;        mov ax,3d00h                    ; Open the file        mov dx,offset response+2        int 21h        mov bx,ax        jc failure        mov ax,3f00h                    ; Read the file        mov dx,100h        push es        pop ds        mov cx,0FF00h        int 21h        jc failure        mov cx,ax                       ; Szie of prog in CX        mov ax,3e00h                    ; close the file        int 21h        jc failure                push cx        push es;; Now we free the resources of this loader program.  Note this will; leave a memory gap- a better solution would to have been to free it; BEFORE allocating memory.  Of course then we have to move ourselves; out of the way;        mov es,cs:[2ch]                 ; free our environment        mov ah,49h        int 21h                push cs                         ; Free our program seg        pop es        mov ah,49h        int 21h;; Now we have to inform DOS that the active PSP has changed.  It is normal; to eventually restore the PSP in TSRs but we won't be coming back; later.;        mov bx,ds                       ; Inform DOS about the new PSP        mov ah,50h        int 21h        pop es        pop cx;; Now we set up the segment registers and such.  The registers we; are initializing are as follows:;; DS,ES,SS,Sp,CS,IP; BX:CX;; AFAIK that is all that has to be initialized.  But maybe you ought to; write a short program to dump the registers at startup of a com file; and see?  Don't depend on DEBUG... it zeros the registers but DOS; doesn't do that.        cli                             ; Set stack pointer to new process        push ds        pop ss        mov sp,0fff0h        sti        sub bx,bx                       ; Put the null in case they        push bx                         ; use RET to exit        push ds                         ; set the CS:IP pair to run prog        push 100h        retfeop:        end start    

Ps: I also have a exe ver if you interestard.
If you do not want to use Dos, i have some code for that too (eg: own OS)
Post 27 Oct 2006, 17:04
View user's profile Send private message Reply with quote

Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 28 Oct 2006, 03:58
Link to the above-mentioned .COM and .EXE loaders by David Lindauer: http://ladsoft.tripod.com/demos.htm
Post 28 Oct 2006, 03:58
View user's profile Send private message Visit poster's website Reply with quote

Joined: 27 Apr 2006
Posts: 339
sylwek32 28 Oct 2006, 22:17
has somebody already converted it to fasm syntax?
Post 28 Oct 2006, 22:17
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-2023, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.