如何在不使用从C导出的函数的情况下在Linux中使用NASM程序集获得系统时间?

时间:2015-01-05 10:31:48

标签: linux assembly x86 nasm x86-64

我正在为我的大学做一个项目。任务是打印当前日期和时间。 我成功完全设法创建了一个打印数字的子程序,我现在需要的只是获取日期。 我试过了this approach:

%define RTCaddress  0x70
%define RTCdata     0x71

;Get time and date from RTC
.l1:    mov al,10           ;Get RTC register A
        out RTCaddress,al
        in al,RTCdata
        test al,0x80            ;Is update in progress?
        jne .l1             ; yes, wait

        mov al,0            ;Get seconds (00 to 59)
        out RTCaddress,al
        in al,RTCdata
        mov [RTCtimeSecond],al

但只是打电话:

.l1:    mov al,10           ;Get RTC register A
        out RTCaddress,al

是否应该崩溃。你知道如何修复这种方法,或者我可以使用任何不同的方法。 我在Linux 64bit上使用Nasm。

1 个答案:

答案 0 :(得分:2)

正如Jester指出Jpowel answered 类似 question。 JPowel提供了适用于32位和64位的答案。调用int 0x80的兼容性(在64位Linux上)与其相关的额外开销很少。 64位特定方法是使用64位指令SYSCALLsys_time内核例程。 Linux sys_time联机帮助页是here。它将sys_time定义为:

  

概要

  #include <time.h>

  time_t time(time_t *t);
     

说明

  time() returns the time as the number of seconds since the Epoch,
  1970-01-01 00:00:00 +0000 (UTC).

  If t is non-NULL, the return value is also stored in the memory
  pointed to by t.

可以在Ryan Chapmans blog上找到64位Linux syscall的良好资源。此信息对于使用64位System V ABI内核调用约定设置sys_time调用非常有用。他的桌子有:

%rax  System call    %rdi
---------------------------------
201   sys_time       time_t *tloc

此代码提供了一个使用指向sys_time类型(long long)的指针调用time_t的示例,并显示了传递0作为第一个参数的第二种方法,它只返回{{1}中的时间1}}。

rax

根据C库 section .data time: dq 0 global _start section .text _start: ; Method 1: pass a pointer to a time_t (long long) to return time in ; sys_time = syscall(201, *long long) mov rax, 201 ; system call 0xC9(201) = sys_time mov rdi, time ; address of long long (qword) to return ; a time_t val syscall ; make Linux system call ; Method 2: pass zero as the time_t parameter. sys_time returns ; value in rax . ; sys_time = syscall(201, *long long = 0) mov rax, 201 ; system call 0xC9(201) = sys_time xor rdi, rdi ; address of long long (qword) set to zero syscall ; make Linux system call ; Do something useful with time ; Seconds since 1970-01-01 00:00:00 +0000 (UTC) ; Exit with the time mov rdi, rax ; return least sig byte of time as return code mov rax, 60 ; system call 0x3C(60) is exit syscall ; make Linux system call 函数的源代码,此Stackoverflow answer建议在C中实现合理的实现。将它转换为X86_64汇编程序并不困难。代码很简单。使用这样的功能可以分解单个组件进行格式化的时间并不困难。