32位汇编语言学习笔记(38)--显示命令行参数(2)

来源:互联网 发布:java从入门到精通mobi 编辑:程序博客网 时间:2024/05/29 18:08


showargs1程序是把命令行参数字符串的地址从栈中拷贝到全局数组变量里,然后把结果显示出来,showargs2程序对此进行了改进,直接从栈上读取命令行参数字符串的地址,而不再进行拷贝操作,程序大同小异:

SECTION .data; Section containing initialised dataErrMsg db "Terminated with error.",10ERRLEN equ $-ErrMsgSECTION .bss; Section containing uninitialized data; This program handles up to MAXARGS command-line arguments. Change the; value of MAXARGS if you need to handle more arguments than the default 10.; Argument lengths are stored in a table. Access arg lengths this way:;[ArgLens + <index reg>*4]; Note that when the argument lengths are calculated, an EOL char (10h) is; stored into each string where the terminating null was originally. This; makes it easy to print out an argument using sys_write. MAXARGS   equ  10; Maximum # of args we supportArgLens:  resd MAXARGS; Table of argument lengthsSECTION .text; Section containing codeglobal _start; Linker needs this to find the entry point!_start:nop; This no-op keeps gdb happy...mov ebp,esp; Save the initial stack pointer in EBP; Copy the command line argument count from the stack and validate it:cmp dword [ebp],MAXARGS; See if the arg count exceeds MAXARGSja Error; If so, exit with an error message; Here we calculate argument lengths and store lengths in table ArgLens:xor eax,eax; Searching for 0, so clear AL to 0xor ebx,ebx; Stack address offset starts at 0ScanOne:mov ecx,0000ffffh; Limit search to 65535 bytes maxmov edi,dword [ebp+4+ebx*4] ; Put address of string to search in EDImov edx,edi; Copy starting address into EDX                                                                                                                                                                                                                                                                                                             cld; Set search direction to up-memoryrepne scasb; Search for null (0 char) in string at edijnz Error; REPNE SCASB ended without finding ALmov byte [edi-1],10; Store an EOL where the null used to besub edi,edx; Subtract position of 0 from start addressmov dword [ArgLens+ebx*4],edi; Put length of arg into tableinc ebx; Add 1 to argument countercmp ebx,[ebp]; See if arg counter exceeds argument countjb ScanOne; If not, loop back and do another one; Display all arguments to stdout:xor esi,esi; Start (for table addressing reasons) at 0Showem:mov ecx,[ebp+4+esi*4]; Pass offset of the messagemov eax,4; Specify sys_write callmov ebx,1; Specify File Descriptor 1: Standard Outputmov edx,[ArgLens+esi*4]; Pass the length of the messageint 80H; Make kernel callinc esi; Increment the argument countercmp esi,[ebp]; See if we've displayed all the argumentsjb Showem; If not, loop back and do anotherjmp Exit; We're done! Let's pack it in!Error: mov eax,4; Specify sys_write callmov ebx,1; Specify File Descriptor 2: Standard Errormov ecx,ErrMsg; Pass offset of the error messagemov edx,ERRLEN; Pass the length of the messageint 80H; Make kernel callExit:mov eax,1; Code for Exit Syscallmov ebx,0; Return a code of zeroint 80H; Make kernel call

程序分析:
 mov ebp,esp  //ebp =esp,保存栈指针到ebp
 cmp dword [ebp],MAXARGS //比较ebp保存的地址指向的内存的内容(命令行参数个数),与最大参数个数
 ja Error  //如果大于,跳转到Error

 xor eax,eax  //eax=0,al=0
 xor ebx,ebx  //ebx=0
ScanOne:
 mov ecx,0000ffffh //ecx=65535
 mov edi,dword [ebp+4+ebx*4]  //edi = &ebp[ebx*4+4],命令行参数的首地址
 mov edx,edi //edx=edi                                                                                                                                                                                                                                                 
 cld   //清除DF标志,内存地址变化方向从低到高
 repne scasb  //扫描字符串,如果遇到0,则结束。
 jnz Error  //如果循环结束,ZF标志位没有设置,则说明ecx=0,属于异常情况,跳转到Error
 mov byte [edi-1],10  //字符串的结尾的0字符替换成10(换行符)
 sub edi,edx  //算出字符串长度,包括换行符
 mov dword [ArgLens+ebx*4],edi //保存长度到数组中
 inc ebx   //ebx=ebx+1
 cmp ebx,[ebp]  //比较ebx和命令行参数个数
 jb ScanOne  //如果小于继续循环

 xor esi,esi  //esi=0
Showem:
 mov ecx,[ebp+4+esi*4] //ecx=命令行参数字符串起始地址
 mov eax,4  
 mov ebx,1  
 mov edx,[ArgLens+esi*4] //字符串长度
 int 80H   
 inc esi   //esi = esi +1
 cmp esi,[ebp] //比较esi与命令行参数个数
 jb Showem  //小于继续循环
 jmp Exit 

测试:

[root@bogon showargs2]# makenasm -f elf -g -F stabs showargs2.asm -l showargs2.lstld -o showargs2 showargs2.o[root@bogon showargs2]# ./showargs2 p1 p2./showargs2p1p2


0 0
原创粉丝点击