这里的第一个问题是您需要了解 sys_time 系统调用。http://syscalls.kernelgrok.com/上有一个方便的图表,它告诉您各种 sys 调用需要哪些作为寄存器的输入。
sys_time 是系统调用 13,所以
mov eax,13
很好
但是 sys_time 还需要在 ebx 中传递一个内存地址,它会在其中写入实际时间。
一种快速的方法是在堆栈上分配一些空间(我们可以将任何东西压入堆栈,sys_time 值会覆盖它,为什么不将 eax 的值粘贴到它上面)。
push eax
然后将堆栈指针输入 ebx
mov ebx, esp
现在进行系统调用
int 80h
现在我们可以将时间从堆栈中弹出(例如eax)
pop eax
现在 eax 包含当前的 unix 时间(即自 1970 年 1 月 1 日以来的秒数。)
为了避免将数字直接打印到 unix 控制台的复杂性,我将作弊并提供一个完整的示例,该示例在 nasm 中编译并通过 gcc 与 c 库链接并使用 printf
[SECTION .data]
PrintNum db "%d",10,0 ;this is a c string so is null terminated
[SECTION .text]
extern printf
global main
main:
push ebp
mov ebp,esp
push ebx
push esi
push edi ; stuff before this for glibc compatibility
mov eax, 13
push eax
mov ebx, esp
int 0x80
pop eax
push eax ; push eax onto stack then the format string, then call printf to write eax to console, unwind stack pointer
push PrintNum
call printf
add esp,8
pop edi ; stuff after this for glibc compatibility
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
编译
nasm -f elf sys_time.asm
gcc sys-time.o -o sys-time
尽管如果您使用的是 64 位 linux,您可能必须这样做(并且拥有相关的 multilib gcc 和 glibc)。您不能将此程序编译为本机 64 位可执行文件,因为它使用 push 和 pop,并且您无法将 32 位寄存器压入 64 位堆栈。
nasm -f elf32 sys_time.asm
gcc -m32 sys-time.o -o sys-time
那么你应该得到
$ ./systime
1310190574
我已经在 32 位和 64 位 linux 上对此进行了测试,并设法编译了上述代码。如果您有任何问题,请告诉我。
为了回答您关于 nasm 教程的问题,我最近一直在学习 Jeff Duntemann 的“Assembly Language Step By Step, Third Edition”。有关详细信息和示例章节,请参见http://www.duntemann.com/assembly.html。