⑴ 汇编 语言实现在命令行参数中输入文件名打开文件感谢各位大神
以下是汇编编译的com文件执行外部程序的示例。供参考:
;***********************************************************
;*本程序由程序ASMPAS.EXE自动生成*
;*版权所有:lifangqing1997年2月7日*
;***********************************************************
code segment
org100h
assumecs:code
start: jmpBEGIN
nop
stackarea dw100p(?)
stacktop dw0
oldss dw?
oldsp dw?
loadp dw0
COM_OFSdw0080h
COM_SEGdw?
dw005ch
dw?
dw006ch
dw0
dw20p(?)
SHELL DB'C:COMMAND.COM',0
shell_PARAdb12,'/cshell.exe',13
UP_PARADB9,'/CUP.BAT',13
Q_U_PARADB7,'/CQUIT',13
L62_PARADB9,'/Cqbasic',13
L61_PARADB13,'/Cbasica.exe',13
L42_PARADB9,'/Cqbasic',13
L41_PARADB13,'/Cbasica.exe',13
L22_PARADB9,'/Cqbasic',13
L21_PARADB13,'/Cbasica.exe',13
CHAR DB?
ERR1MSGDB'CHANGEMEMERROR',10,13,'$'
ERR2MSGDB'EXECERROR',10,13,'$'
MENUADDDB'C:PAS_IDEmenu.EXE',0
;*****************CTRL_BREAK中断处理代码************
CTRL_BREAK:
IRET
;*****************正常及出错退出代码****************
;******************************************************************
ERROR:
MOVSS,OLDSS
MOVSP,OLDSP
int20h
;***************************************************************
;修改STACK和重新设置CTRL-BREAK向量
;****************************************************************
BEGIN:
PUSHCS
POPDS
MOVOLDSS,SS
MOVOLDSP,SP
MOVAX,CS
MOVSS,AX
MOVSP,OFFSETSTACKTOP
CALLCHANGEMEM
MOVAH,33H
MOVAL,1
MOVDL,0
INT21H
PUSHDS
MOVAX,0
MOVDS,AX
MOVSI,008CH
CLI
MOVWORDPTR[SI],OFFSETCTRL_BREAK
;原为将FF53放到DS:[SI]中
PUSHCS
POPAX
MOVWORDPTR[SI+2],AX
;原为将F000放到DS:[SI+2]中
STI
POPDS
;****************************************************************
;使数据段指向代码段
;清屏
;显示菜单
;取返回码,将其放入变量CHAR中
;****************************************************************
INIT:
PUSHCS
POPDS
PUSHCS
POPES
MOVAH,15
INT10H
MOVAH,0
INT10H
LEADX,SHELL
MOVWORDPTR[COM_OFS],OFFSETUP_PARA
PUSHCS
POPAX
MOVWORDPTR[COM_SEG],AX
CALLEXEC
menu:
LEADX,menuadd
MOVWORDPTR[COM_OFS],0
MOVWORDPTR[COM_SEG],0
CALLEXEC
movah,4dh
int21h
movbyteptrchar,al
;*************WriteCMOS**************
CMPBYTEPTRCHAR,62
JNENEXT62
LEADX,SHELL
LEAAX,L62_PARA
CALLRUN
JMPMENU
NEXT62:
;*************ReadCMOS**************
CMPBYTEPTRCHAR,61
JNENEXT61
LEADX,SHELL
LEAAX,L61_PARA
CALLRUN
JMPMENU
NEXT61:
;*************WriteDosBootSector**************
CMPBYTEPTRCHAR,42
JNENEXT42
LEADX,SHELL
LEAAX,L42_PARA
CALLRUN
JMPMENU
NEXT42:
;*************ReadDosBootSector**************
CMPBYTEPTRCHAR,41
JNENEXT41
LEADX,SHELL
LEAAX,L41_PARA
CALLRUN
JMPMENU
NEXT41:
;*************WriteMainBootRecord**************
CMPBYTEPTRCHAR,22
JNENEXT22
LEADX,SHELL
LEAAX,L22_PARA
CALLRUN
JMPMENU
NEXT22:
;*************ReadMainBootRecord**************
CMPBYTEPTRCHAR,21
JNENEXT21
LEADX,SHELL
LEAAX,L21_PARA
CALLRUN
JMPMENU
NEXT21:
CMPBYTEPTRCHAR,81
JNENEXT81
LEADX,SHELL
LEAAX,Q_U_PARA
CALLRUN
JMPERROR
NEXT81:
JMPMENU
;**************************************************************
;执行外部程序
;入口参数:
;DX-----路径文件名ASCZ串偏移
;AX-----命令行参数PASCAL串偏移
;**************************************************************
RUNPROCNEAR
LEADX,SHELL
MOVWORDPTR[COM_OFS],AX
PUSHCS
POPAX
MOVWORDPTR[COM_SEG],AX
CALLEXEC
RET
RUNENDP
;***********加载UCDOS及打印部分****************
UPPROCNEAR
LEADX,SHELL
MOVWORDPTR[COM_OFS],OFFSETUP_PARA
PUSHCS
POPAX
MOVWORDPTR[COM_SEG],AX
CALLEXEC
RET
UPENDP
;***********退出UCDOS****************
QUITPROCNEAR
LEADX,SHELL
MOVWORDPTR[COM_OFS],OFFSETQ_U_PARA
PUSHCS
POPAX
MOVWORDPTR[COM_SEG],AX
CALLEXEC
RET
QUITENDP
;*************************************************************
;执行子进程(路径文件名在DX中:入口参数)
;*************************************************************
EXEC PROCNEAR
PUSHCS
POPES
MOVBX,OFFSETLOADP
MOVAX,CS
MOV[BX+4],AX
MOV[BX+8],AX
MOV[BX+12],AX
MOVAX,4B00H
INT21H
JNCNO1
MOVAH,9
LEADX,ERR2MSG
INT21H
POPAX
POPAX
JMPERROR
NO1: RET
EXEC ENDP
;*************************************************************
;改变内存块大小
;*************************************************************
CHANGEMEM PROCNEAR
MOVAX,OFFSETTAIL
SHRAX,1
SHRAX,1
SHRAX,1
SHRAX,1
INCAX
PUSHCS
POPES
MOVBX,AX
MOVAH,4AH
INT21H
JNCNO2
MOVAH,9
LEADX,ERR1MSG
INT21H
POPAX
POPAX
JMPERROR
NO2:
RET
CHANGEMEM ENDP
TAIL:
CODE ENDS
ENDSTART
⑵ 怎么获取汇编命令行参数
PROCESS_BASIC_INFORMATION pbi;
PEB2 peb;
PROCESS_PARAMETERS ppa;
wchar_t pa[255];
NtQueryInformationProcess(ProcessHandle,ProcessBasicInformation,(void *) &pbi,sizeof(PROCESS_BASIC_INFORMATION),0);
ReadProcessMemory(ProcessHandle,pbi.PebBaseAddress,(void *) &peb,sizeof(PEB2),0);
ReadProcessMemory(ProcessHandle,peb.ProcessParameters,(void *) &ppa,sizeof(PROCESS_PARAMETERS),0);
ReadProcessMemory(ProcessHandle,ppa.CommandLine.Buffer,pa,ppa.CommandLine.Length,0);
linux下将C语言编译为汇编代码,需用-S参数: 编译命令为: $ gcc -S s1.c 如下代码: void fun(int a,int b){ /*这个函数什么也不做*/}int main(void){ fun(100,200); return 0;}
⑷ C语言如何获得命令行参数
C语言获得命令行参数的方法 每当你运行一个DOS或Windows程序时,都会生成一个程序段前缀(Program SegmentPrefix,简称PSP)。当DOS程序的装入程序把程序复制到RAM中来执行时,它先把256个字节分配给PSP,然后把可执行代码复制到紧接着PSP的内存区域中。PSP中包含了DOS为了执行一个程序所需要的各种各样的信息,其中的一部分数据就是命令行。PSP中偏移量为128的那个字节中存放着命令行中的字符个数,接下来的127个字节中存放着命令行本身。这也正是DOS把你能在其提示行中输入的字符个数限制在127个之内的原因——因为它为命令行分配的存储空间只有那么多。遗憾的是,PSP的命令行缓冲区中并没有存放可执行程序的名字——而只存放着在可执行程序名后键入的字符(包括空格符)。例如,如果你在DOS提示行中键入以下命令: XCOPY AUTOEXEC.BAT AUTOEXEC.BAK 假设XCOPY.EXE存放在c驱动器的DOS目录下,则XCOPY.EXE的PSP命令行缓冲区中将包含以下信息: AUTOEXEC.BAT AUTOEXEC.BAK 注意,命令行中紧接着"XCOPY"的空格符也被复制到PSP的缓冲区中。 除了不能在PSP中找到可执行程序名外,PSP还有一个不足之处——在命令行中能看到的对于输出或输入的重定向,在PSP的命令行缓冲区中是无法看到的,也就是说,你无法从PSP中得知你的程序是否被重定向过。 到现在为止,你应该熟悉在C程序中可以通过argc和argv来获取一些有关信息,但是,这些信息是怎样从DOS的装入程序传给argv指针的呢?这是由程序的启动代码来完成的。启动代码在main()函数的第一行代码之前被执行,在其执行期间,它调用一个名为__setargv()的函数,把程序名和命令行从PSP和DOS环境中复制到mai‘n()函数的argv指针所指向的缓冲区中。你可以在xLIBCE.LIB文件中找到_setargv()函数,对于Small,Medium和Large这三种存储模式,这里的“x”分别为“S”,“M”和“L”。在生成可执行程序时,上述库文件会自动被连接进来。除了复制argv参数的内容外,c的启动代码还要完成其它一些工作。当启动代码执行完毕后,main()函数中的代码就开始执行了。 在DOS中的情况是这样的,那么在Windows中的情况又是怎样的呢?实际上,在Windows中的情况大致上和在DOS中的一样。当执行一个Windows程序时,与DOS的装入程序一样,Windows的装入程序也会建立一个PSP,其中包含了与DOS的PSP中相同的信息。主要的区别是此时命令行被复制到lpszCmdLine参数中,它是WinMain()函数的参数表中的第三个(也是倒数第二个)参数。在Windows C的xLIBCEW.LIB库文件中包含了启动函数setargv(),它负责把命令行信息复制到lpszCmdLine缓冲区中。同样,这里的“x”也表示程序所使用的存储模式。在Quick c中,函数_setargv()包含在库文件xLIBCEWQ.LIB中。 尽管DOS程序和Windows程序的命令行信息的管理方式基本相同,但是传给你的C程序的命令行的格式在安排上稍有不同。在DOS中,启动代码获得以空格符为分隔符的命令行后,就把每个参数转换为其自身的以NULL为终止符的字符串。因此,你可把argv原型化为一个指针数组(char* argv[]),并通过从O到n这些下标值来访问每个参数,其中n等于命令行中的参数个数减去1。你也可以把argv原型化为一个指向指针的指针(char **argv),并通过增减argv的值来访问每一个参数。 在Windows中,传给c程序的命令行是一个LPSTR类型或char_far*类型,其中的每一个参数都用空格符隔开,就象你在DOS提示行中键入这些字符后所看到的那样(实际上,在Windows中不可能真正键入这些字符,而是通过双击应用程序图标这样的方式来启动一个程序)。为了访问Windows命令行中的各个参数,你必须人工地访问lpszCmdLine所指向的存储区,并分隔存放在该处的参数,或者使用strtok()这样的函数,每次处理一个参数。 如果你富于探索精神,你可以仔细地研究PSP本身,并从中获取命令行信息。为此,你可以像下面这样来使用DOS中断21H(此处使用Microsoft C): # include <stdio. h # incIude <dos. h main(int argc,char **argv){union REGS regs ; / * DOS register access struct * / char far * pspPtr; / * pointer to PSP * / int cmdLineCnt; / *num of chars in cmd line * / regs. h. ah=0x62; /*use DOS interrupt 62 *; int86(0x21 ,®s,&egs) ; / *call DOS * / FP-SEG(pspPtr) =regs. x. bx ; / *save PSP segment * / FP_OFF(pspPtr)=0xS0; / * set pointer offset * / / * * pspPtr now points to the command-line count byte * / cmdLineCnt== * pspPtr ; 需要注意的是,在Small存储模式下,或者在只有一个代码段的汇编程序中,由DOS返回到BX寄存器中的值就是程序代码段的地址值;在Large模式的c程序中,或者在多个代码段的汇编程序中,所返回的值是程序中包含PSP的那个代码段的段地址值。如果你已经建立了一个指向这个数据的指针,你就可以在程序中使用这个数据了。 今天,通常你可以认为你的程序可以使用命令行参数。但是,在DOS 2.O版以前,存储在PSP中的命令行信息与现在稍有不同(它不能从命令行中分离出输入或输出重定向数据),而 且由argv[O]所指向的数据中并不一定包含可执行程序的路径名。直到DOS发展到3.o版,它才提供了(或者说至少公开了)用来检索PSP的中断62H。因此,你至少可以认为,在运行DOS3.0或更高版本的PC上,你的程序总是可以获得命令行参数的。 如果你的程序运行在DOS 3.0或更高的版本下,你基本上就可以任意处理命令行参数了,因为这些信息已存入栈中供你使用。显然,适用于栈中数据的常规的数据操作规则同样也适用于存入栈中的命令行参数。然而,如果你的编译程序不提供argv参数,例如当你用汇编语言或者某种不提供argv参数的编译程序编写程序时,真正的问题就出现了。在这种情况下,你将不得不自己找出检索命令行参数的方法,而使用DOS中断62H就是一种很方便的方法。 如果你要用DOS中断62H来检索指向命令行的指针,你必须明白该指针所指向的数据是供DOS使用的,并且正在被DOS使用。尽管你可以检索这些数据,但你不可以改变它们。如果在程序中需要随时根据命令行参数作出决定,那么在使用这些数据之前应该先把它们复制到一个局部缓冲区中,这样就可以随意处理这些数据,而不用担心会与DOS发生冲突了。实际上,这种技巧同样适用于带argv参数的c程序。位于main()函数之外的函数需要使用命令行参数的情况并不少见,为了使这些函数能引用这些数据,main()函数必须把这些数据存为全局型,或者通过(再次)入栈把它们传递给需要使用它们的函数。
⑸ 如何编写带命令行参数的汇编程序
一个全世界通用的方法是,在程序可能出错的地方打入代码桩,如打入MessageBoxA跟踪显示关键变量是否正确,后锁定那部分代码出错;
如
--------------
A段
MessageBoxA("A ok")
B段
MessageBoxA("B ok")
C段
------------
如果根据程序启动运行显示的信息锁定哪部分代码出问题,之后再检测错误代码不同时刻的变量值是否合理合法,阿门。。。
⑹ 汇编语言中命令行参数是什么意思
http://bbs.csdn.net/topics/310054390
⑺ 用汇编解释C语言中printf的参数为什么是不确定的,如何实现的
//32 bit 汇编调用printf
//call printf (fmt,a1,a1,a3,a4.....an)
;调用的数据压入栈,由于宽度不知道,所以用伪代码表示.
push a5
push a4
push a3
push a2
push a1
push offset fmt
call printf
sub esp,sizeof(an)+..........+sizeof(a4)+sizeof(a3)+sizeof(a2)+sizeof(a1)
printf 的C实现
//实际上 用汇编的时候,跳过返回地址就是所有参数的首地址
//mov ebx ,DWORD PTR esp[8] ; //fmt 的地址
//mov esi, DOWRD ptr esp[12] //a1的地址
char**pVarList= &fmt;//fmt 在堆栈最低端。是个地址,所以他的地址就是所有参数的首地址
pVarList++;
for( i=0;i<strlen(fmt);i++)
{
if(*p='%'){
split(&p,w0,w1,s,f)
//p格式的下一个字符,s所代表w0,w1 %8.2f w0=8w1=2 +号-号, case 'U','u'里的 ‘U’,'u'
switch(f)
{
case 'U','u':如果 是%8U %u %-8 U f=U
unsigned int *pU=(unsigned int*)pVarList;
putUint(*pU,w0,s);所代表 +号-号
pU++;
pVarList=pU;
break;
case 'F','f':....
.{
unsigned int *pF=(unsigned int*)pVarList;
putFloat(*pF,w0,w1,s);
pU++;
pVarList=pF;
}
break;
case ......
break;
}
}
else if(*p=='\')
dealbackslash(&p);//同样 p指向\格式的最后一个字符的
else putc(*p++);
}
//32 bit
//call printf (fmt,a1,a1,a3,a4,a5)
push a5
push a4
push a3
push a2
push a1
push offset fmt
call printf
sub esp,sizeof(a5)+sizeof(a4)+sizeof(a3)+sizeof(a2)+sizeof(a1)
//16bit
//call printf (fmt,a1,a1,a3,a4,a5)
push a5
push a4
push a3
push a2
push a1
push offset fmt
call printf
sub sp,sizeof(a5)+sizeof(a4)+sizeof(a3)+sizeof(a2)+sizeof(a1)
⑻ 请问在 Win32 汇编中如何获取每个命令行参数
用GetCL这个API,如invoke GetCL,1,addr MyFullName获取第一个参数(获取成功eax返回1)
⑼ 汇编命令 CALL 的是什么参数
00453E50 /$ 51 PUSH ECX ;
00453E51 |. 53 PUSH EBX
00453E52 |. 56 PUSH ESI //保存环境
00453E53 |. 8BF1 MOV ESI,ECX //esi = ecx = 第一个参数
00453E55 |. 8B4E 14 MOV ECX,DWORD PTR DS:[ESI+14]
看这段代码,应该是fastcall调用方式,该调用方式是使用ecx来传第一个参数,edx来传第二个参数,其他的使用堆栈来传递。00453E50这个函数在这部分只看出有一个参数,其他的参数不确定,找一下函数返回的地方,看返回几个参数。
我猜这里可能只有一个参数,即该函数调用:fun_00453E50(esi)
00471A12 |. 8BCE MOV ECX,ESI //ecx = esi = 第一个参数
00471A14 |. E8 3724FEFF CALL elementc.00453E50。
补充:汇编指令是汇编语言中使用的一些操作符和助记符,还包括一些伪指令(如assume,end)。用于告诉汇编程序如何进行汇编的指令,它既不控制机器的操作也不被汇编成机器代码,只能为汇编程序所识别并指导汇编如何进行。
⑽ 汇编怎么取命令行参数
首先问句:你的数据段呢?如果有数据段,ASSUMECS:CSEG,DS:CSEG只是说明,并没有把CSEG赋值给DS,要使用MOVAX,DSEGMOVDS,AX来实现赋值。