为什么在 libc nanosleep 中的寄存器 rax 上有一个紧密的轮询循环?
Why is there a tight polling loop on register rax in libc nanosleep?
libc-2 中 nanosleep 的反汇编。7.so 在 64 位 Linux 上看起来像这样:
Disassembly of section .text:
00000000000bd460 <__nanosleep>:
cmpl [=10=]x0,__libc_multiple_threads
jne 10
00000000000bd469 <__nanosleep_nocancel>:
mov [=10=]x23,%eax
syscal
10: cmp [=10=]xfffffffffffff001,%rax
jae 40
retq
sub [=10=]x8,%rsp
callq __libc_enable_asynccancel
mov %rax,(%rsp)
mov [=10=]x23,%eax
syscal
mov (%rsp),%rdi
mov %rax,%rdx
callq __libc_disable_asynccancel
mov %rdx,%rax
add [=10=]x8,%rsp
40: cmp [=10=]xfffffffffffff001,%rax
jae 40
retq
mov _DYNAMIC+0x2e0,%rcx
neg %eax
mov %eax,%fs:(%rcx)
or [=10=]xffffffffffffffff,%rax
retq
在这段汇编代码的底部附近,有这个轮询循环:
40: cmp [=11=]xfffffffffffff001,%rax
jae 40
在执行此循环时,rax
的值将如何变化?它不会永远循环还是根本不循环?这个循环是为了完成什么?
我怀疑这与 syscall
指令有关,因为 syscall
的 return 值被放入寄存器 rax
,但我不确定这是怎么回事完全相关。代码的编写方式使它 看起来 就像 syscall
不会阻塞并且 rax
中的值会自发更改,但这似乎不正确。
我很想知道这里发生了什么。
我没有看到这些自旋循环。
这是我从 objdump -d /lib/x86_64-linux-gnu/libc.so.6
获得的内容,您显示的循环用 **
突出显示,它们跳转到的地址用 ->
。
00000000000c0f10 <__nanosleep>:
c0f10: 83 3d 5d 31 30 00 00 cmpl [=10=]x0,0x30315d(%rip) # 3c4074 <argp_program_version_hook+0x1cc>
c0f17: 75 10 jne c0f29 <__nanosleep+0x19>
c0f19: b8 23 00 00 00 mov [=10=]x23,%eax
c0f1e: 0f 05 syscall
c0f20: 48 3d 01 f0 ff ff cmp [=10=]xfffffffffffff001,%rax
** c0f26: 73 31 jae c0f59 <__nanosleep+0x49>
c0f28: c3 retq
c0f29: 48 83 ec 08 sub [=10=]x8,%rsp
c0f2d: e8 3e 72 04 00 callq 108170 <pthread_setcanceltype+0x80>
c0f32: 48 89 04 24 mov %rax,(%rsp)
c0f36: b8 23 00 00 00 mov [=10=]x23,%eax
c0f3b: 0f 05 syscall
c0f3d: 48 8b 3c 24 mov (%rsp),%rdi
c0f41: 48 89 c2 mov %rax,%rdx
c0f44: e8 87 72 04 00 callq 1081d0 <pthread_setcanceltype+0xe0>
c0f49: 48 89 d0 mov %rdx,%rax
c0f4c: 48 83 c4 08 add [=10=]x8,%rsp
c0f50: 48 3d 01 f0 ff ff cmp [=10=]xfffffffffffff001,%rax
** c0f56: 73 01 jae c0f59 <__nanosleep+0x49>
c0f58: c3 retq
-> c0f59: 48 8b 0d 08 cf 2f 00 mov 0x2fcf08(%rip),%rcx # 3bde68 <_IO_file_jumps+0x7c8>
c0f60: f7 d8 neg %eax
c0f62: 64 89 01 mov %eax,%fs:(%rcx)
c0f65: 48 83 c8 ff or [=10=]xffffffffffffffff,%rax
c0f69: c3 retq
c0f6a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
其余代码类似。可能是反汇编的问题?
libc-2 中 nanosleep 的反汇编。7.so 在 64 位 Linux 上看起来像这样:
Disassembly of section .text:
00000000000bd460 <__nanosleep>:
cmpl [=10=]x0,__libc_multiple_threads
jne 10
00000000000bd469 <__nanosleep_nocancel>:
mov [=10=]x23,%eax
syscal
10: cmp [=10=]xfffffffffffff001,%rax
jae 40
retq
sub [=10=]x8,%rsp
callq __libc_enable_asynccancel
mov %rax,(%rsp)
mov [=10=]x23,%eax
syscal
mov (%rsp),%rdi
mov %rax,%rdx
callq __libc_disable_asynccancel
mov %rdx,%rax
add [=10=]x8,%rsp
40: cmp [=10=]xfffffffffffff001,%rax
jae 40
retq
mov _DYNAMIC+0x2e0,%rcx
neg %eax
mov %eax,%fs:(%rcx)
or [=10=]xffffffffffffffff,%rax
retq
在这段汇编代码的底部附近,有这个轮询循环:
40: cmp [=11=]xfffffffffffff001,%rax
jae 40
在执行此循环时,rax
的值将如何变化?它不会永远循环还是根本不循环?这个循环是为了完成什么?
我怀疑这与 syscall
指令有关,因为 syscall
的 return 值被放入寄存器 rax
,但我不确定这是怎么回事完全相关。代码的编写方式使它 看起来 就像 syscall
不会阻塞并且 rax
中的值会自发更改,但这似乎不正确。
我很想知道这里发生了什么。
我没有看到这些自旋循环。
这是我从 objdump -d /lib/x86_64-linux-gnu/libc.so.6
获得的内容,您显示的循环用 **
突出显示,它们跳转到的地址用 ->
。
00000000000c0f10 <__nanosleep>:
c0f10: 83 3d 5d 31 30 00 00 cmpl [=10=]x0,0x30315d(%rip) # 3c4074 <argp_program_version_hook+0x1cc>
c0f17: 75 10 jne c0f29 <__nanosleep+0x19>
c0f19: b8 23 00 00 00 mov [=10=]x23,%eax
c0f1e: 0f 05 syscall
c0f20: 48 3d 01 f0 ff ff cmp [=10=]xfffffffffffff001,%rax
** c0f26: 73 31 jae c0f59 <__nanosleep+0x49>
c0f28: c3 retq
c0f29: 48 83 ec 08 sub [=10=]x8,%rsp
c0f2d: e8 3e 72 04 00 callq 108170 <pthread_setcanceltype+0x80>
c0f32: 48 89 04 24 mov %rax,(%rsp)
c0f36: b8 23 00 00 00 mov [=10=]x23,%eax
c0f3b: 0f 05 syscall
c0f3d: 48 8b 3c 24 mov (%rsp),%rdi
c0f41: 48 89 c2 mov %rax,%rdx
c0f44: e8 87 72 04 00 callq 1081d0 <pthread_setcanceltype+0xe0>
c0f49: 48 89 d0 mov %rdx,%rax
c0f4c: 48 83 c4 08 add [=10=]x8,%rsp
c0f50: 48 3d 01 f0 ff ff cmp [=10=]xfffffffffffff001,%rax
** c0f56: 73 01 jae c0f59 <__nanosleep+0x49>
c0f58: c3 retq
-> c0f59: 48 8b 0d 08 cf 2f 00 mov 0x2fcf08(%rip),%rcx # 3bde68 <_IO_file_jumps+0x7c8>
c0f60: f7 d8 neg %eax
c0f62: 64 89 01 mov %eax,%fs:(%rcx)
c0f65: 48 83 c8 ff or [=10=]xffffffffffffffff,%rax
c0f69: c3 retq
c0f6a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
其余代码类似。可能是反汇编的问题?