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



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

SECTION .data			; Section containing initialised data

	ErrMsg db "Terminated with error.",10
	ERRLEN equ $-ErrMsg
	
SECTION .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 support
	ArgLens:  resd MAXARGS	; Table of argument lengths

SECTION .text			; Section containing code

global 	_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 MAXARGS
	ja 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 0
	xor ebx,ebx		; Stack address offset starts at 0
ScanOne:
	mov ecx,0000ffffh	; Limit search to 65535 bytes max
	mov edi,dword [ebp+4+ebx*4] ; Put address of string to search in EDI
	mov edx,edi		; Copy starting address into EDX                                                                                                                                                                                                                                                                                                             
	cld			; Set search direction to up-memory
	repne scasb		; Search for null (0 char) in string at edi
	jnz Error		; REPNE SCASB ended without finding AL
	mov byte [edi-1],10	; Store an EOL where the null used to be
	sub edi,edx		; Subtract position of 0 from start address
	mov dword [ArgLens+ebx*4],edi	; Put length of arg into table
	inc ebx			; Add 1 to argument counter
	cmp ebx,[ebp]		; See if arg counter exceeds argument count
	jb ScanOne		; If not, loop back and do another one

; Display all arguments to stdout:
	xor esi,esi		; Start (for table addressing reasons) at 0
Showem:
	mov ecx,[ebp+4+esi*4]	; Pass offset of the message
	mov eax,4		; Specify sys_write call
	mov ebx,1		; Specify File Descriptor 1: Standard Output
	mov edx,[ArgLens+esi*4]	; Pass the length of the message
	int 80H			; Make kernel call
	inc esi			; Increment the argument counter
	cmp esi,[ebp]	; See if we've displayed all the arguments
	jb Showem		; If not, loop back and do another
	jmp Exit		; We're done! Let's pack it in!

Error: 	mov eax,4		; Specify sys_write call
	mov ebx,1		; Specify File Descriptor 2: Standard Error
	mov ecx,ErrMsg		; Pass offset of the error message
	mov edx,ERRLEN		; Pass the length of the message
	int 80H			; Make kernel call

Exit:	mov eax,1		; Code for Exit Syscall
	mov ebx,0		; Return a code of zero	
	int 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]# make
nasm -f elf -g -F stabs showargs2.asm -l showargs2.lst
ld -o showargs2 showargs2.o
[root@bogon showargs2]# ./showargs2 p1 p2
./showargs2
p1
p2


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值