NASM汇编Linux计时器或睡眠

3
我试图找到一种方法,在继续执行之前使我的代码等待两秒钟。我正在使用Linux中的nasm保护模式,因此只能使用int 80h。我发现一个名为“alarm”(27)和另一个名为“pause”(29)的syscall。但是,当我尝试使用它们时,程序会等待并完成而不是继续执行。我还发现另一个syscall,sigaction,它可以更改信号的行为(所以我认为可以用来忽略由alarm引起的信号而不是退出程序),但我没有完全理解sigaction如何工作。谢谢任何帮助。
有用的链接:http://man7.org/linux/man-pages/man2/alarm.2.htmlhttp://man7.org/linux/man-pages/man2/sigaction.2.html

阅读time(7)并跟随链接浏览其他 man 手册。 - Basile Starynkevitch
一个更正,你正在使用NASM进行用户空间编程,所以你不处于保护模式下。 - rakib_
2个回答

10

有一个用于让程序睡眠的系统调用,sys_nanosleep

 sys_nanosleep : eax = 162, ebx = struct timespec *, ecx = struct timespec *

这个struct timespec结构体有两个成员:

 ;; This is for 32-bit.  Note that x86-64 uses 2x 64-bit members
tv_sec   ; 32 bit seconds
tv_nsec  ; 32 bit nanoseconds

这个结构可以在NASM中声明为:

section .data

  timeval:
    tv_sec  dd 0
    tv_usec dd 0

然后您设置值并将其调用为:

mov dword [tv_sec], 5
mov dword [tv_usec], 0
mov eax, 162
mov ebx, timeval
mov ecx, 0
int 0x80

程序接下来将休眠5秒钟。完整示例:

global  _start

section .text
_start:

  ; print "Sleep"
  mov eax, 4
  mov ebx, 1
  mov ecx, bmessage
  mov edx, bmessagel
  int 0x80

  ; Sleep for 5 seconds and 0 nanoseconds
  mov dword [tv_sec], 5
  mov dword [tv_usec], 0
  mov eax, 162
  mov ebx, timeval
  mov ecx, 0
  int 0x80

  ; print "Continue"
  mov eax, 4
  mov ebx, 1
  mov ecx, emessage
  mov edx, emessagel
  int 0x80

  ; exit
  mov eax, 1
  mov ebx, 0
  int 0x80

section .data

  timeval:
    tv_sec  dd 0
    tv_usec dd 0

  bmessage  db "Sleep", 10, 0
  bmessagel equ $ - bmessage

  emessage  db "Continue", 10, 0
  emessagel equ $ - emessage

2

使用NASM,如果你的目标是Linux x86-64,你可以简单地执行以下类似的操作:

global _start

section .data

    timespec:
        tv_sec  dq 1
        tv_nsec dq 200000000

section .text

    _start:
        mov rax, 35
        mov rdi, timespec
        xor rsi, rsi        
        syscall
        ...
35 对应于64位系统调用号,用于调用sys_nanosleep(在此处列出)。如果调用被中断,则剩余的睡眠时间将被写入由寄存器rsi指向的内存位置;在本例中,rsi设置为0以忽略该值。此调用将休眠tv_sec秒+tv_nsec纳秒,在上述代码片段中为1.2秒。
有关此系统调用的更多信息,请参见nanosleep手册页

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接