32位汇编语言学习笔记(42)--测试时间相关函数



此程序出自《Assembly Language step by step programming with linux》第12章,用于演示时间相关的libc库函数的使用,程序中使用了如下的libc库函数:
time_t time( time_t *timer );
char *ctime( const time_t *timer );
double difftime( time_t timer1, time_t timer0 );
struct tm *localtime( const time_t *timer );
int getchar( void );

程序如下:

[SECTION .data]			; Section containing initialised data

TimeMsg  db "Hey, what time is it?  It's %s",10,0
YrMsg	 db "The year is %d.",10,0
Elapsed  db "A total of %d seconds has elapsed since program began running.",10,0	
	
[SECTION .bss]			; Section containing uninitialized data

OldTime	 resd 1			; Reserve 3 integers (doubles) for time values
NewTime  resd 1
TimeDiff resd 1	
TimeStr  resb 40		; Reserve 40 bytes for time string
TmCopy	 resd 9			; Reserve 9 integer fields for time struct tm			
[SECTION .text]			; Section containing code

extern ctime
extern difftime
extern getchar
extern printf
extern localtime	
extern time
									
global main			; Required so linker can find entry point
	
main:
    push ebp		; Set up stack frame for debugger
	mov ebp,esp
	push ebx		; Program must preserve EBP, EBX, ESI, & EDI
	push esi
	push edi
;;; Everything before this is boilerplate; use it for all ordinary apps!	

; Generate a time_t calendar time value with clib's time function
	push 0			; Push a 32-bit null pointer to stack,
				;   since we don't need a buffer.
	call time		; Returns calendar time in EAX
	add esp,4		; Clean up stack after call
	mov [OldTime],eax	; Save time value in memory variable

; Generate a string summary of local time with clib's ctime function
	push OldTime		; Push address of calendar time value
	call ctime		; Returns pointer to ASCII time string in EAX
    add esp,4		; Stack cleanup for 1 parm

	push eax		; Push pointer to ASCII time string on stack
	push TimeMsg		; Push pointer to base message text string
	call printf		; Merge and display the two strings
	add esp,8		; Stack cleanup: 2 parms X 4 bytes = 8

; Generate local time values into clib's static tm struct
	push dword OldTime	; Push address of calendar time value
	call localtime		; Returns pointer to static time structure in EAX
	add esp,4		; Stack cleanup for 1 parm

; Make a local copy of clib's static tm struct
	mov esi,eax		; Copy address of static tm from eax to ESI
	mov edi,TmCopy		; Put the address of the local tm copy in EDI
	mov ecx,9		; A tm struct is 9 dwords in size under Linux
	cld			; Clear DF so we move up-memory
	rep movsd		; Copy static tm struct to local copy

; Display one of the fields in the tm structure
	mov edx,dword [TmCopy+20] ; Year field is 20 bytes offset into tm
	add edx,1900		; Year field is # of years since 1900
	push edx		; Push value onto the stack
	push YrMsg		; Push address of the base string
	call printf		; Display string and year value with printf
	add esp,8		; Stack cleanup: 2 parms X 4 bytes = 8
		
; Wait a few seconds for user to press Enter so we have a time difference:
	call getchar		; Wait for user to press Enter
	
; Calculating seconds passed since program began running:
	push dword 0		; Push null ptr; we'll take value in EAX
	call time		; Get current time value; return in EAX
	add esp,4		; Clean up the stack	
	mov [NewTime],eax	; Save new time value
	
	sub eax,[OldTime]	; Calculate time difference value
	mov [TimeDiff],eax	; Save time difference value
	
	push dword [TimeDiff]	; Push difference in seconds onto the stack
	push Elapsed		; Push addr. of elapsed time message string
	call printf		; Display elapsed time
	add esp,8		; Stack cleanup for 1 parm	
			
;;; Everything after this is boilerplate; use it for all ordinary apps!
	pop edi			; Restore saved registers
	pop esi
	pop ebx
	mov esp,ebp		; Destroy stack frame before returning
	pop ebp
	ret			; Return control to Linux


程序分析:
push 0  //函数参数timer=NULL
 call time  //调用time函数,返回当前时间,用与1970年1月1日0点0分0秒的相差的秒数表示。
 add esp,4  //清理栈
 mov [OldTime],eax //保存返回值到OldTime变量

 push OldTime  // 函数参数timer= OldTime
 call ctime  //调用ctime函数,返回时间信息字符串
add esp,4  //清理栈

push eax  //时间字符串压入堆栈
 push TimeMsg  //时间显示格式
 call printf  //调用printf函数,打印时间信息
 add esp,8  //清理栈,因为两个参数,所以加8

push dword OldTime //函数参数 timer= OldTime
 call localtime  //调用localtime函数,对时间值进行转换,返回tm结构体的指针。
 add esp,4  //清理栈

 mov esi,eax  //esi是源,保存返回的tm结构体的地址
 mov edi,TmCopy  //edi=TmCopy,指定拷贝的目的地址
 mov ecx,9  //ecx用于循环计数,tm结构体是9个dword,因此ecx=9
 cld   //清除DF标志,控制地址变化方向从低到高
 rep movsd  //进行拷贝,把返回的tm结构体拷贝到TmCopy

    mov edx,dword [TmCopy+20]  //edx=TmCopy的year字段
 add edx,1900  //因为tm保存的是与1900年的差值,因此要加1900
 push edx  //把年份参数压入堆栈
 push YrMsg  //格式化字符串
 call printf  //调用printf函数打印年份信息
 add esp,8     //清理栈

call getchar  //等待用户键入回车键
 
 push dword 0  //函数参数timer=NULL
 call time  //调用time函数,返回当前时间。
 add esp,4  //清理栈
 mov [NewTime],eax //把当前时间值保存到NewTime中。
 
 sub eax,[OldTime] //用NewTime- OldTime的值放入eax
 mov [TimeDiff],eax //差值保存到TimeDiff中
 
 push dword [TimeDiff] //把差值作为函数参数,压入堆栈
 push Elapsed  //格式化字符串压入堆栈
 call printf  //调用printf函数,显示消耗的秒数信息。
 add esp,8  //清理栈

makefile文件内容:

timetest: timetest.o
	gcc timetest.o -o timetest
timetest.o: timetest.asm
	nasm -f elf -g -F stabs timetest.asm


测试:

[root@bogon timetest]# make
nasm -f elf -g -F stabs timetest.asm
gcc timetest.o -o timetest
[root@bogon timetest]# ./timetest
Hey, what time is it?  It's Wed Jan 14 15:12:39 2015

The year is 2015.

A total of 2 seconds has elapsed since program began running.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值