2012-04-04 10 views
9

私はこれに対する解決策が切望されています。私はアセンブリコードを開発して、2つの他のアセンブリ.EXEプログラムをロードして(ユーザーの入力によって)実行できるようにしようとしています。私は他を実行できるようにする必要があり、私は有効なレジスタ(または多分間違った構文)にパス名を割り当てることができていないようプログラムをRAMにロードして実行するNASM 16b

    • :私は2つの問題を抱えています最初のプログラムが実行された後に(そのいずれかになりうる)プログラムの実行が開始されました。

    これは私がこれまで持っているものです。

    mov ax,cs ; moving code segment to data segment 
    mov ds,ax 
    
    mov ah,1h ; here I read from keyboard 
    int 21h 
    mov dl,al 
    
    cmp al,'1' ; if 1 jump to LOADRUN1 
    JE LOADRUN1 
    
    cmp al,'2' ; if 2 jump to LOADRUN2 
    JE LOADRUN2 
    
    LOADRUN1: 
        MOV AH,4BH 
        MOV AL,00 
        LEA DX,[PROGNAME1] ; Not sure if it works 
        INT 21H 
    
    
    LOADRUN2: 
        MOV AH,4BH 
        MOV AL,00 
        LEA DX,[PROGNAME2] ; Not sure if it works 
        INT 21H 
    
    ; Here I define the bytes containing the pathnames 
    PROGNAME1 db 'C:\Users\Usuario\NASM\Adding.exe',0 
    PROGNAME2 db 'C:\Users\Usuario\NASM\Substracting.exe',0 
    

    1が既に実行された後、私は、「親」プログラムに入力することにより、別のプログラムを起動する方法がわかりません。

    ご協力いただきありがとうございます。追加情報は私が提供することを喜んで提供します。

    • オーバーレイではありません。
    • 私はNASM 16ビット、Windows 7 32ビットを使用しています。
  • +2

    本当に助けが必要です。私の評判はすべて報酬として与えられます。 –

    +1

    DOS( 'int 21h')APIは、廃止された、効果のない、かなり使われていない不要なソフトウェアです。これはもう使用してはいけません。あなたは絶対に**あなたはそれを使う必要があると確信していますか? –

    +2

    @DanielKozarはい、絶対に。私はそうでなければ私の評判を払わないだろう。私は本当にこれについて助けが必要です。 –

    答えて

    7

    いくつかのハッキングとツイディリングの後、私はこの作業を得ることができました。それは私が望むほど簡単ではありませんので、あなたの座席をつかんでください。

    まず、DOSはシングルユーザーでマルチタスクではないシステムであることを認識する必要があります。この特定の場合、2つのプロセスを同時に実行することはできません。 が必要です。あるプロセスが別のプロセスに移動する前に実行を完了するのを待つ必要があります。プロセスの並行処理は、TSR(Terminate and Stay Resident)プロセスでいくらかエミュレートされる可能性があります。プロセスは終了したにもかかわらずメモリに残り、コードからいくつかの割り込みをフックし、後で別のコードから呼び出すことで実行を再開できます。それでも、WindowsやLinuxなどの最新のOSで使用されているのと同じ種類の並行性はありません。しかし、それはポイントではなかった。

    NASMをアセンブラとして使用していると言われましたので、コードをCOMファイルに出力し、DOSコマンドプロンプトでコードを実行すると仮定しました。 COMフ​​ァイルは、コマンドプロンプトでオフセット100h(その場所へのジャンプを実行した後に実行されます)でロードされ、 "リーン"なコードとデータ以外のものは含まれません。ヘッダーがないため、生成するのが最も簡単です。

    私はアセンブリのソースを断片的に説明していますので、ボンネットの下で起こっていることをよりよく見ることができます(おそらく)。

    プログラムは

    org 100h 
    
    section .data 
    exename db "C:\hello.com",0 
    exename2 db "C:\nasm\nasm.exe",0 
    cmdline db 0,0dh 
    

    実際にメモリにロードされたファイルの起源を特定しorgディレクティブで始まる - 我々の場合には、これは100hです。 3つのラベルの宣言は、実行するプログラムのNULL終端されたパスであるexenameexename2と、新しく作成されたプロセスが受け取るべきコマンドラインを指定するcmdlineです。最初のバイトはコマンドラインの文字数、次にコマンドライン自体、およびキャリッジリターンであることに注意してください。この場合、コマンドラインパラメータはありません。したがって、すべてがdb 0,0dhになります。 paramsとして-h -x 3を渡したいとします。この場合、このラベルをdb 8," -h -x 3",0dhと宣言する必要があります(冒頭の余分なスペースに注意してください)。移動...

    dummy times 20 db 0 
    
    paramblock dw 0 
    dw cmdline 
    dw 0 ; cmdline_seg 
    dw dummy ; fcb1 
    dw 0 ; fcb1_seg 
    dw dummy ; fcb2 
    dw 0 ; fcb2_seg 
    

    ラベルdummyは、ゼロを含むわずか20バイトです。以下は、paramblockラベルです。これは、Daniel Roethlisbergerが言及したEXEC構造の表現です。最初の項目はゼロです。つまり、新しいプロセスは親プロセスと同じ環境を持つ必要があります。コマンドライン、最初のFCB、2番目のFCBの3つのアドレスが続きます。実際のモードのアドレスは、セグメントのアドレスとセグメントへのオフセットという2つの部分で構成されています。これらのアドレスは両方とも16ビット長です。彼らはリトルエンディアン方式でメモリに書き込まれ、最初はオフセットされています。したがって、コマンドラインをオフセットcmdline、FCBのアドレスをラベルdummyへのオフセットとして指定します。これは、FCB自体は使用されませんが、アドレスは有効なメモリ位置を指す必要があるためです。ローダーがCOMファイルがロードされるセグメントを選択するため、セグメントは実行時に埋められる必要があります。

    paramblock構造のセグメントフィールドを設定してプログラムを開始します。 COMフ​​ァイルの場合、CS = DS = ES = SS、つまりすべてのセグメントが同じであるため、これらの値をcsレジスタの値に設定するだけです。

    mov  ax, 4a00h 
    mov  bx, 50 
    int  21h 
    

    これは実際にアプリケーションの最も難しい点の1つです。 COMフ​​ァイルがDOSによってメモリにロードされると、デフォルトで使用可能なすべてのメモリが割り当てられます(CPUはリアルモードであるため、DOS内部ではそれを追跡します)。したがって、EXECシステムコールを呼び出すと、それはNo memory availableで失敗します。したがって、私たちはDOSに "RESIZE MEMORY BLOCK" AH=4Ahコール(Ralf Brown)を実行することによって、そのメモリをすべて必要としないことを伝える必要があります。 bxレジスタは16バイト単位でメモリブロックの新しいサイズ( "段落")を持つはずですので、プログラムには800バイトを持つ50に設定します。この値は無作為に選ばれたことを認めなければなりません。実際のファイルサイズに基づく値など、意味をなさないものに設定しようとしましたが、私はどこにも行きませんでした。ESは、「サイズ変更」したいセグメントです。この場合、CS(またはCOMファイルがロードされても同じなので、他のものもあります)です。この呼び出しが完了したら、新しいプログラムをメモリにロードして実行する準備が整いました。

    mov  ax, 0100h 
        int  21h 
        cmp  al, '1' 
        je  .prog1 
        cmp  al, '2' 
        je  .prog2 
        jmp  .end 
    
    .prog1: 
        mov  dx, exename 
        jmp  .exec 
    
    .prog2: 
        mov  dx, exename2 
    

    このコードは、それが標準入力に基づいDXに挿入したプログラムへのパスを選択し、かなり自明であるべきです。

    .exec: 
        mov  bx, paramblock 
        mov  ax, 4b00h 
        int  21h 
    
    EXEC

    実際のシステムコール(AH=4Bh)が呼び出されるところです。 ALには0が含まれているため、プログラムをロードして実行する必要があります。 DS:DXには、実行可能ファイルへのパスのアドレス(以前のコードで選択されています)が含まれています。ES:BXには、EXEC構造を含むparamblockラベルのアドレスが含まれています。

    .end: 
        mov  ax,  4c00h 
        int  21h 
    

    execによって呼び出されたプログラムの実行を終了した後、親プログラムがAH=4Chシステムコールを実行することにより、ゼロの終了コードで終了します。

    vulture-ありがとうございます。## asm on Freenodeからお問い合わせください。私はこれをDOSBoxとMS-DOS 6.22でテストしました。うまくいけば、あなたのためにもうまくいきます。

    +0

    これと同時に2つのプログラムを実行できると思いますか? –

    +4

    **あなたは** **文字通り**を同時に実行するアプリケーションを持つことはできません。 DOSではこれを許可していません。 –

    +1

    @DanielKamilKozar:いい答えです。これはまったく1980年代です... –

    4

    this referenceによると、あなたはEXECパラメータブロックを設定されていません。

    Format of EXEC parameter block for AL=00h,01h,04h: 
    
    Offset Size Description  (Table 01590) 
    00h WORD segment of environment to copy for child process (copy caller's 
    environment if 0000h) 
    02h DWORD pointer to command tail to be copied into child's PSP 
    06h DWORD pointer to first FCB to be copied into child's PSP 
    0Ah DWORD pointer to second FCB to be copied into child's PSP 
    0Eh DWORD (AL=01h) will hold subprogram's initial SS:SP on return 
    12h DWORD (AL=01h) will hold entry point (CS:IP) on return 
    

    参照されたページは、ページを読み込むことは困難である理由です、この表のため<pre>/</pre>タグを欠いています。

    このようなパラメータブロックを設定し、ES:BXをそのアドレスに設定する必要があります。


    代わりのWin32 APIのあなたは16ビット(DOS用API)を標的にしているいずれかの特定の理由がありますか?あなたが代わりのWin32 APIを標的にして逃げることができますと仮定すると、あなたはこのスケルトンのようなものでWinExecコールを使用して外部の実行ファイルを起動することができます。

    global [email protected] 
    
    ; WinExec(char *lpCmdLine, int uCmdShow) 
    extern [email protected] 
    
    [section .code] 
    [email protected]: 
        ; ... read input and jump to loadrun1 or loadrun2 here 
    
    loadrun1: 
        push dword 1 
        push dword progname1 
        call [email protected] 
        ret 
    
    loadrun2: 
        push dword 1 
        push dword progname2 
        call [email protected] 
        ret 
    
    [section .data] 
        progname1 db 'C:\Users\Usuario\NASM\Adding.exe',0 
        progname2 db 'C:\Users\Usuario\NASM\Substracting.exe',0 
    

    代わりに、より近代的なShellExecuteコールを使用することができます。

    +1

    私はいくつかのコースをやっているので、私は16ビットを設計する必要があります。 16ビットのDOS用に書かれたソリューションで私を助けることができると思いますか?それはgrealy感謝されるでしょう。そして、ところで、私はちょうどそれらのpopfを取り除くべきですか? –

    +1

    はい、 'popf'命令を削除するだけです。 –

    +0

    16ビットのヒントを追加するように編集しました。 DOS(a.k.a Windows :)を実行しないので、実際にこれをテストすることはできません。 –

    関連する問題