【发布时间】:2012-04-20 15:58:02
【问题描述】:
以下 C 函数尝试使用线程本地存储变量以线程安全的方式防止多核代码中的递归。但是,由于有些复杂的原因,我需要在 X64 汇编器(Intel X86 / AMD 64 位)中编写此函数,并使用 VC2010 中的 ml64.exe 进行汇编。如果我使用全局变量,我知道如何执行此操作,但我不确定如何使用具有 __declspec(thread) 的 TLS 变量正确执行此操作。
__declspec(thread) int tls_VAR = 0;
void norecurse( )
{
if(0==tls_VAR)
{
tls_VAR=1;
DoWork();
tls_VAR=0;
}
}
注意:这是 VC2010 踢出的功能。但是,MASM (ml64.exe) 不支持代码的gs:88 或OFFSET FLAT: 部分。
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.40219.01
include listing.inc
INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES
PUBLIC norecurse
EXTRN DoWork:PROC
EXTRN tls_VAR:DWORD
EXTRN _tls_index:DWORD
pdata SEGMENT
$pdata$norecurse DD imagerel $LN4
DD imagerel $LN4+70
DD imagerel $unwind$norecurse
pdata ENDS
xdata SEGMENT
$unwind$norecurse DD 040a01H
DD 06340aH
DD 07006320aH
; Function compile flags: /Ogtpy
xdata ENDS
_TEXT SEGMENT
norecurse PROC
; File p:\hackytests\64bittest2010\64bittest\64bittest.cpp
; Line 19
$LN4:
mov QWORD PTR [rsp+8], rbx
push rdi
sub rsp, 32 ; 00000020H
; Line 20
mov ecx, DWORD PTR _tls_index
mov rax, QWORD PTR gs:88
mov edi, OFFSET FLAT:tls_VAR
mov rbx, QWORD PTR [rax+rcx*8]
cmp DWORD PTR [rbx+rdi], 0
jne SHORT $LN1@norecurse
; Line 22
mov DWORD PTR [rbx+rdi], 1
; Line 23
call DoWork
; Line 24
mov DWORD PTR [rbx+rdi], 0
$LN1@norecurse:
; Line 26
mov rbx, QWORD PTR [rsp+48]
add rsp, 32 ; 00000020H
pop rdi
ret 0
norecurse ENDP
_TEXT ENDS
END
【问题讨论】:
-
您是否查看了 VC 生成的用于 tls 变量访问的代码并在您的程序集中重现该代码?
-
你应该标记这个 MSVC 或 windows 什么的。其他所有问题的答案都会大不相同。
-
@Mat:是的,我做到了。我不知道如何在 ml64.exe 中使用 gs 的常量偏移量,但我可以将常量移动到寄存器并以这种方式访问它。几个额外的步骤,但它可能会起作用。
标签: c windows assembly thread-local thread-local-storage