2012-04-04 11 views
9

Bunun için bir çaresizim. Montaj kodu geliştirmeye çalışıyorum (kullanıcı girdisi ile) 2 diğer Assembly .EXE programlarını yüklememe ve çalıştırma. İki sorun yaşıyorum:Programları RAM'e yükleme ve yürütme NASM 16b

  • Ben diğer yürütmek gerekiyor

  • geçerli bir kayıt için yolu atamak mümkün (Ya da belki yanlış sözdizimi) olmak görünmüyor

    Birinciden sonra program (ya da olabilir) infazını başlattı.

    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 
    

    Sadece 'ebeveyn' programında girişi ile başka bir program başlatmak için nasıl bilmiyorum, biri zaten yürütme sonra:

Bu defa ne var.

Yardımlarınız için şimdiden teşekkür ederiz! Ek bilgi vermekten mutluluk duyacağım.

  • Kaplama değildir.
  • NASM 16 bit, Windows 7 32 bit kullanıyorum.
+2

Gerçekten bir yardıma ihtiyacım var. –

+1

DOS ('int 21h') API'si artık kullanılmaması gereken bir mutlak, etkisiz, oldukça fazla kullanılmayan ve istenmeyen bir yazılım parçasıdır. ** Kesinlikle kullanmanız gerektiğinden emin misiniz? –

+2

@DanielKozar Evet, kesinlikle. Aksine itibarımı vermezdim. Bunun için yardıma ihtiyacım var. –

cevap

7

Bazı korsanlıktan ve çığlık atmadan sonra, bu çalışmayı başarabiliyordum. Umduğum kadar basit değil, bu yüzden koltuğunuza oturun. Öncelikle, DOS'un tek kullanıcılı, çok işlevli olmayan bir sistem olduğunu farketmeniz gerekir. Bu özel durumda, eşzamanlı olarak çalışan iki sürece sahip olamayacağınız anlamına gelir. , başka bir işleme taşınmadan önce bir işlemin yürütmeyi bitirmesini beklemek için gerekir. Süreç eşzamanlılığı TSR (Terminate ve Stay Resident) süreçleriyle bir şekilde taklit edilebilir, bu da sonlandırılmalarına rağmen bellekte kalır ve kodlarından bazı kesintiler alarak ve daha sonra başka bir koddan çağrılarak yürütme işlemlerine devam edilebilir. Yine de, Windows ve Linux gibi modern işletim sistemlerinde kullanılan aynı türde bir eşzamanlılık değil. Ama konu bu değildi.

NASM'yi seçtiğiniz bir derleyiciniz olarak kullandığınızı söylemiştiniz, bu nedenle kodunuzu, COM komut satırında çalıştırılan COM dosyalarına çıkardığınızı varsaydım. COM dosyaları, 100h ofsetinde (bu konuma bir atlama yüklendikten sonra) komut istemiyle yüklenir ve başka bir şey içermez, ancak "yalın" kod ve veri içermez - üstbilgiler, bu nedenle üretilmesi en kolay olanıdır.

Montaj kaynağını parçalar halinde açıklayacağım, böylece (belki de) kaputun altında neler olup bittiğini daha iyi anlayabilirsiniz.

programı

org 100h 

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

aslında belleğe yüklenen dosyanın kaynağını belirtir org direktifi ile başlar - bizim durumumuzda, bu 100h olduğunu. Üç etiketin bildirimleri, yürütülecek programların boş sonlandırılmış yolları olan exename ve exename2 ve yeni oluşturulan işlemin alması gereken komut satırını belirten cmdline izler. Sadece normal bir dize olmadığını unutmayın: ilk bayt, komut satırındaki karakterlerin sayısı, daha sonra komut satırının kendisi ve bir Carriage Return'dır. Bu durumda, hiçbir komut satırı parametresine sahip değiliz, bu yüzden her şey db 0,0dh'a kadar kaynar. Paragraf olarak -h -x 3'u geçmek istediğimizi varsayalım: bu durumda, bu etiketi db 8," -h -x 3",0dh olarak bildirmeliyiz (başlangıçta fazladan boşluk bırakın!). Etiket dummy ...

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 

Devam ediyoruz sıfır içerecektir sadece 20 bayt. Aşağıda, Daniel Roethlisberger tarafından belirtilen EXEC yapısının bir temsili olan paramblock etiketi yer almaktadır. İlk öğe sıfırdır, bu da yeni sürecin ebeveyniyle aynı ortama sahip olması gerektiği anlamına gelir. Üç adres takip eder: komut satırına, ilk FCB'ye ve ikinci FCB'ye. Gerçek modda adreslerin iki bölümden oluştuğunu unutmamalısınız: segmentin adresi ve segmente ofset. Her iki adres de 16 bit uzunluğundadır. Ofisinde ilk başta küçük bir endian tarzında yazılıyorlar. Bu nedenle, cmdline ofseti olarak komut satırını ve FCB'lerin adreslerini dummy etiketine ofset olarak belirtiriz, çünkü FCB'lerin kendileri kullanılmayacak, ancak adresler her iki durumda da geçerli bir bellek konumuna işaret etmelidir. Yükleyiciler, COM dosyasının yüklü olduğu segmenti seçtiğinden, bölümlerin çalışma zamanında doldurulması gerekir.

section .text 
entry: 
    mov  ax,    cs 
    mov  [paramblock+4], ax 
    mov  [paramblock+8], ax 
    mov  [paramblock+12],ax 

Biz paramblock yapısında segmenti alanları belirleyerek programı başlayacak. COM dosyaları için, CS = DS = ES = SS, yani tüm bölümler aynı olduğundan, bu değerleri yalnızca cs kaydında olanlara ayarladık.

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

Bu aslında uygulamanın en zor noktalarından biridir. Bir COM dosyası DOS tarafından belleğe yüklendiğinde, varsayılan olarak tüm kullanılabilir bellek atanır (CPU, gerçek modda olduğu için bu konuda hiçbir fikre sahip değildir, ancak DOS internals yine de izler). Bu nedenle, EXEC syscall çağrısı, No memory available ile başarısız olmasına neden olur. Bu nedenle, DOS'a "RESIZE MEMORY BLOCK" AH=4Ah numaralı telefonu aratarak gerçekten bu belleğe gerek duymadığımızı söylemeliyiz. bx kaydının, bellek bloğunun yeni boyutuna 16 baytlık birimlerde ("paragraf") sahip olması gerekiyordu, bu yüzden programımız için 800 bayta sahip olan 50'ye ayarladık. Bu değerin rastgele seçildiğini itiraf etmeliyim, bunu mantıklı bir şeye ayarlamayı denedim (örneğin, gerçek dosya boyutuna dayalı bir değer), ama hiçbir yere ulaşamadım.ES, "yeniden boyutlandırmak" istediğimiz bölümdür, bizim durumumuzda CS (veya bir COM dosyası yüklendiğinde hepsi aynı olduğundan, herhangi biri). Bu aramayı tamamladıktan sonra, yeni programımızı belleğe yüklemek ve yürütmek için hazırız.

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 

Bu kod stdin dayalı DX yerleştirilen programa yolunu seçer, yeterince açıklayıcı olmalıdır. Gerçek EXEC syscall (AH=4Bh) olarak adlandırılır burada

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

olmasıdır. AL, 0 içerir, bu da programın yüklenmesi ve çalıştırılması gerektiği anlamına gelir. DS:DX, yürütülebilir dosyanın yolunun adresini (önceki kod parçası tarafından seçilir) ve ES:BX, EXEC yapısını içeren paramblock etiketinin adresini içerir.

.end: 
    mov  ax,  4c00h 
    int  21h 

exec tarafından çağrılan program yürütme tamamlandıktan sonra, ana program AH=4Ch çağrısını yürüterek sıfır olan bir çıkış kodu ile sonlandırılır.

Yardım için Freenode üzerindeki ## asm adresinden vulture- aracılığıyla. Bunu DOSBox ve MS-DOS 6.22 ile test ettim, bu yüzden umarım sizin için de çalışır.

+0

Aynı anda 2 programı çalıştırabilir miyim? –

+4

** **, ** aynı anda ** ** çalıştıran uygulamalara sahip olamazsınız. DOS buna izin vermiyor. –

+1

@DanielKamilKozar: Güzel cevap. Bu tamamen 1980'ler ... –

4

this reference göre, EXEC parametre bloğu ayarlarını değildir:

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 

başvurulan sayfası bu tablo için <pre>/</pre> etiketleri yoksun, sayfada okumak zor olmasının nedeni budur.

Böyle bir parametre bloğu kurmanız ve bu adrese ES: BX'i işaretlemeniz gerekecektir.


yerine Win32 API 16 bit (DOS API) hedef alan herhangi bir sebebi var mı? Bunun yerine Win32 API hedefimiz yanında kurtulmak varsayarsak, bu iskelet gibi bir şey WinExec çağrısı kullanarak dış yürütülebilir başlatabilirsiniz:

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 

Alternatif olarak, daha modern ShellExecute çağrısını kullanabilirsiniz.

+1

Birkaç kurs yapıyorum, 16 bit için tasarlamam gerekiyor. 16 bitlik bir DOS için yazılmış bir çözümle bana yardımcı olabileceğini mi düşünüyorsun? Grealy takdir edilecektir. Ve bu arada, o poplardan kurtulmalı mıyım? –

+1

Evet, 'popf' komutlarını kaldırmanız yeterli. –

+0

Bazı 16 bit ipuçları eklemek üzere düzenlenmiştir. DOS (a.k.a. Windows :)) çalıştırmıyorum, bu yüzden bunu test edemiyorum. –

İlgili konular