如何在不使用从 C 导出的函数的情况下在 Linux 中使用 NASM 汇编获取系统时间



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

%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 64 位的 Nasm。

正如杰斯特指出的那样,Jpowel回答了类似的问题。JPowel 提供了一个适用于 32 位和 64 位的答案。通过int 0x80调用的兼容性(在 64 位 Linux 上)具有与之相关的少量额外开销。64 位特定方法是使用 sys_time 内核例程SYSCALL的 64 位指令。Linux sys_time manpage 就在这里。它将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.

64位Linux syscall的一个很好的资源可以在Ryan Chapmans博客上找到。此信息可用于使用 64 位系统 V ABI 内核调用约定设置sys_time调用。他的桌子有:

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

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

        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 答案建议基于 C 库gmtime函数的源代码在 C 中实现一个合理的实现。将其转换为汇编程序并不难X86_64。代码非常简单。有了这样的功能,将时间分解成单独的组件进行格式化一点也不难。

最新更新