32位汇编语言学习笔记(39)--显示环境变量



前面的程序显示了程序的命令行参数,在程序的栈中,在命令行参数字符指针的上面就是保存的环境变量的字符串指针,以下程序用于显示环境变量:

SECTION .data			; Section containing initialised data

	ErrMsg db "Terminated with error.",10
	ERRLEN equ $-ErrMsg
	
SECTION .bss			; Section containing uninitialized data	
	MAXVARS	 equ 300
	VarLens: resd MAXVARS	; 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
	xor eax,eax		; Searching for 0, so clear EAX to 0
	xor esi,esi		; Start (argumentsfor table addressing reasons) at 0
FindEnv:
	mov ecx,0000ffffh	; Limit search to 65535 bytes max
	mov edi,ebp 		; Put address of string to search in EDI
	mov edx,edi		; Copy starting address into EDX                                                                                                                                                                                                                                                                                                             
	cld			; Set search direction to up-memory
	repne scasd		; Search for null ptr in string at edi
	jnz Error		; REPNE SCASB ended without finding AL
	mov ebp,edi		; Env var addrs begin after null ptr
	xor ebx,ebx		; Zero EBX for use as addr counter

; We now have the address of the first env var address in EBP. Now we scan
; through them and determine their lengths:
ScanOne:
	mov ecx,0000ffffh	; Limit search to 65535 bytes max
	mov edi,dword [ebp+ebx*4] ; Put address of string to search in EDI
	cmp edi,0		; See if we hit the second null ptr
	je Showem		; If so, we've scanned em all, so show 'em
	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 [VarLens+ebx*4],edi	; Put length of var into table
	inc ebx			; Add 1 to environment variable counter
	jmp ScanOne		; If not, loop back and do another one

; Display all environment variables to stdout:
Showem:
	mov ecx,[ebp+esi*4]	; Pass offset of the environment var
	mov eax,4		; Specify sys_write call
	mov ebx,1		; Specify File Descriptor 1: Standard Output
	mov edx,[VarLens+esi*4]	; Pass the length of the message
	int 80H			; Make kernel call
	inc esi			; Increment the env var counter
	cmp dword [ebp+esi*4],0	; See if we've displayed all the variables
	jne 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,保存当前的栈指针
 xor eax,eax  //eax=0
    xor esi,esi         //esi=0
FindEnv:
 mov ecx,0000ffffh //ecx=65535
 mov edi,ebp   //edi=ebp,ebp指向的栈位置存放命令行参数个数,在此上方依次保存命令行参数字符串的地址,然后是空指针,接下来就是环境变量字符串的地址。
 mov edx,edi  //edx=edi                                                                                                                                                                                                                                                                                                            
 cld   //清除DF标志位,控制字符地址扫描方向由低到高
 repne scasd  //按照4字节进行扫描,直到找到0(eax里面保存的是0)。
 jnz Error  //如果ZF标志位未设置,说明循环结束是因为ecx=0,对于这种异常情况,跳转到Error
 mov ebp,edi  //ebp=edi,edi此时指向空指针上方的栈的位置,因此是环境变量字符串指针数组的起始位置
 xor ebx,ebx  //ebx清零

ScanOne:
 mov ecx,0000ffffh //ecx=65535
 mov edi,dword [ebp+ebx*4] //把环境变量字符串地址装入edi
 cmp edi,0  //如果环境变量字符串地址是0,说明环境变量字符串数组已经到末尾了
 je Showem  //如果是0,退出循环,跳转到Showem,显示环境变量
 mov edx,edi  //edx=edi,保存edi值
 cld   //清除DF标志位,控制字符地址扫描方向由低到高
 repne scasb  //扫描字符串,直到遇到0字符
 jnz Error  //如果ZF标志位未设置,说明循环结束是因为ecx=0,对于这种异常情况,跳转到Error
 mov byte [edi-1],10  //把0字符换成换行符
 sub edi,edx  //获取字符串的长度,长度包括换行符
 mov dword [VarLens+ebx*4],edi //保存长度到VarLens数组
 inc ebx   //ebx=ebx+1
 jmp ScanOne  //继续循环

Showem:
 mov ecx,[ebp+esi*4] //ecx=环境变量字符串地址
 mov eax,4  
 mov ebx,1  
 mov edx,[VarLens+esi*4] //edx=字符串长度
 int 80H   
 inc esi   //esi=esi+1
 cmp dword [ebp+esi*4],0 //比较环境变量字符串地址和0
 jne Showem  //如果不等于0继续循环
 jmp Exit  

makefile文件内容:

showenv2: showenv2.o
	ld -o showenv2 showenv2.o
showenv2.o: showenv2.asm
	nasm -f elf -g -F stabs showenv2.asm -l showenv2.lst

测试:

[root@bogon showenv2]# make
nasm -f elf -g -F stabs showenv2.asm -l showenv2.lst
ld -o showenv2 showenv2.o
[root@bogon showenv2]# ./showenv2 
SSH_AGENT_PID=4280
HOSTNAME=bogon
DESKTOP_STARTUP_ID=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
WINDOWID=27263057
OLDPWD=/asm/asmsbs3e/chapter11
USER=root
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:
GNOME_KEYRING_SOCKET=/tmp/keyring-lzg8jE/socket
SSH_AUTH_SOCK=/tmp/ssh-NHPLxk4244/agent.4244
SESSION_MANAGER=local/bogon:/tmp/.ICE-unix/4244
MAIL=/var/spool/mail/root
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
DESKTOP_SESSION=default
GDM_XSERVER_LOCATION=local
INPUTRC=/etc/inputrc
PWD=/asm/asmsbs3e/chapter11/showenv2
XMODIFIERS=@im=none
LANG=en_US.UTF-8
GDMSESSION=default
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SHLVL=2
HOME=/root
GNOME_DESKTOP_SESSION_ID=Default
LOGNAME=root
CVS_RSH=ssh
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-huZ90bmSif,guid=c3258403d8a90dafebfc230054b253dd
LESSOPEN=|/usr/bin/lesspipe.sh %s
DISPLAY=:0.0
G_BROKEN_FILENAMES=1
COLORTERM=gnome-terminal
XAUTHORITY=/tmp/.gdmFABESX
_=./showenv2




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值