问题描述
是否有任何 DOS 函数来执行包含 command.com 行的字符串?我需要像 C 的 system()
这样的东西,但对于 DOS 和 FASM。
解决方法
我以前使用过这样的代码来执行 DOS shell 命令。它适用于 nasm,但您可以根据自己的目的对其进行调整。这段代码专门将我们自己的命令行尾部作为 DOS 命令执行,但是如果你想执行不同的命令,你可以在其他一些命令行尾部打补丁。
section .data
comspec db "COMSPEC=" ; for finding COMSPEC in the env block
comlen equ $-comspec
command db "COMMAND.COM",0
; EXEC parameter block
execpar dw 0 ; environment for child (use ours)
dw 80h,0h ; command tail (use ours)
dw 5Ch,0h ; first FCB (use ours)
dw 6Ch,0h ; second FCB (use ours)
section .text
; execute DOS command
doexec:
mov bx,execpar ; EXEC parameter block
mov [bx+4],cs ; fix up segment for command tail
mov [bx+8],cs ; fix up segment for first FCB
mov [bx+12],cs ; fix up segment for second FCB
call fndcom ; write pointer to COMSPEC value to DS:SI
mov dx,si
mov ax,4B00h ; LOAD AND EXECUTE PROGRAM
int 21h
jnc .ok ; error occured?
push ax ; remember error code
call fndcom ; find COMSPEC value anew
pop ax ; restore error code
call perror ; print error message
.ok: push cs ; restore ds
pop ds
ret
; find COMSPEC in the environment block
; and load pointer to it to DS:SI
; preserves bx
fndcom: mov ds,[2Ch] ; environment block
xor si,si ; beginning of env block
; loop invariant: si points to the beginning of
; a string in the environment
.loop1: cmp byte [si],0 ; end of environment reached?
je .nope
mov di,comspec ; find "COMSPEC="
mov cx,comlen ;
repe cmpsb ; compare strings
je .found ; if found,we are done
dec si ; go back to mismatched character
.loop2: lodsb ; search si for end of string
test al,al ; end of string reached?
jne .loop2 ; nope
jmp .loop1 ; check next string in environment
; COMSPEC unset
.nope: push cs
pop ds ; restore ds
mov si,command ; "COMMAND.COM"
ret
; COMSPEC found
.found: ret
基本思想是通过在环境块中搜索名为 COMSPEC
的变量来找到命令解释器的名称。如果没有找到,我们默认为 COMMAND.COM
。然后,我们构建一个 exec parameter block,其中包含我们想要执行的程序的有用细节,包括命令行。这是您需要放置要执行的 shell 命令的地方(以命令行尾部的格式)。最后,我们调用 DOS function 4b00: execute program 来执行命令解释器,运行我们的命令。