32位汇编语言学习笔记(42)--测试时间相关函数
2015-01-15 07:10
405 查看
此程序出自《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 );
程序如下:
程序分析:
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文件内容:
测试:
此程序出自《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.
相关文章推荐
- 32位汇编语言学习笔记(13)--函数的调用
- 32位汇编语言学习笔记(45)--测试简单文件操作接口(完)
- 32位汇编语言学习笔记(41)--fgets等函数的使用
- 32位汇编语言学习笔记(17)--结构体
- windows下32位汇编语言学习笔记 第四章 第一个窗口程序 (windows的消息机制)
- 32位汇编语言学习笔记(18)--联合
- windows下32位汇编语言学习笔记
- windows下32位汇编语言学习笔记
- 32位汇编语言学习笔记(16)--变长数组
- 32位汇编语言学习笔记(15)--定长数组
- windows下32位汇编语言学习笔记 第十章 内存管理部分 1
- 32位汇编语言学习笔记(10)--分析for循环的汇编代码
- windows下32位汇编语言学习笔记 第十章 内存管理部分 2
- 32位汇编语言学习笔记(20)--栈破坏检测
- 32位汇编语言学习笔记(8)--分析do-while循环的汇编代码
- 32位汇编语言学习笔记(14)--递归函数的调用
- 32位汇编语言学习笔记(2)--数据传送指令
- 32位汇编语言学习笔记(4)--移位操作
- 32位汇编语言学习笔记(5)--特殊的算术操作
- 32位汇编语言学习笔记(1)--简单示例