⑴ 匯編 語言實現在命令行參數中輸入文件名打開文件感謝各位大神
以下是匯編編譯的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來實現賦值。