实现永远等待的汇编代码

yfr*_*com 1 linux assembly sleep arm

我想在 Arm Linux 中编写简单而简短的汇编代码,并且永远等待。

label:
b label
Run Code Online (Sandbox Code Playgroud)

这可行,但需要大量 CPU 时间。

我考虑过nanosleep 每 X 秒使用并跳转到标签,但是如何在汇编中使用它?

pause系统调用(在注释中建议)不好,因为该进程有一个信号处理程序。

有简单的方法吗?

Pet*_*des 6

是的,你需要一个系统调用,是的,你的想法都是可行的。(虽然nanosleep受限于 a 可以表示的最大秒数time_t。在 ARM Linux 上这可能“仅”是 2^31-1,众所周知大约是 68 年,从 1970 年到 2038 年 32 位时间溢出的间隔)

然而,Linux 有一个专门用于此目的的系统调用pause(2)

wait() 导致调用进程(或线程)休眠,直到传递信号终止进程或导致调用信号捕获函数

如果您没有安装信号处理程序,暂停无法返回,您只能退出(仍然通过按 control-C,它会传递 SIGINT),或通过杀死它(SIGTERM)或其他正常方式。

如果您确实安装了信号处理程序并且想要继续暂停,那么显然您可以在循环中调用它。(可能最好这样做,而不是在信号处理程序内调用暂停而不是从信号处理程序返回)。您只会在短暂的唤醒期间使用 CPU 时间来运行信号处理程序并重新启动主线程的执行,这将立即调用内核进行另一次暂停。

sleep 和 nanosleep 也会根据处理的信号返回,-EINTR根据手册页返回。(libc 包装函数可能会为您重试/重新启动系统调用,但如果您想使用原始内核调用,则必须自己执行此操作。)


至于如何调用系统调用,搜索site:stackoverflow.comARM系统调用的堆栈溢出(例如google with ),或者一般的google。给定手册页和将 C 参数映射到寄存器的一般方法(调用约定),您可以调用任何内容。 ARM 系统调用的接口是什么?它在 Linux 内核中的何处定义?

暂停不需要参数,因此您只需要__NR_pause右侧寄存器中的调用号 ( ):

@ arm_pause.S   - build with gcc -nostdlib arm_pause.S
#include <asm/unistd.h>   // contains only C preprocessor macros,  no C stuff.

.globl _start
_start:
  mov  r7, #__NR_pause
  swi  0x0
  b   _start        @ rerun if interrupted by a signal
Run Code Online (Sandbox Code Playgroud)

(未经测试;我只arm-none-eabi-gcc安装了,没有安装arm-linux-eabi-gcc。但确认ARM Linux标头确实有__NR_pause,并使用内联asm来检查语法汇编: https: //godbolt.org/z/PerGTx)。

当然,不需要为此使用 asm,您也可以while(1){ pause(); }在 C 中使用,尽管这会调用 libc 包装器来进行系统调用。