, böyle, C adresini önceden yükleyerek derleme dilden bir iş parçacığı yerel bir değişkene erişmeye olmalıdır:
__thread unsigned val;
void incval(void)
{
unsigned *vp = &val;
asm ("incl\t%0" : "+m" (*vp));
}
Bunun nedeni, iş parçacığı yerel değişkenine erişmek için gereken kod sırasının, GCC tarafından desteklenen hemen hemen tüm işletim sistemi ve CPU kombinasyonu için farklı olması ve ayrıca bir yürütülebilir kitaplık yerine (örneğin, -fPIC
ile) bir paylaşılan kitaplık için derleme yapıyorsanız değişiklik göstermesidir. Yukarıdaki yapı, derleyicinin sizin için doğru kod dizisini yayınlamasına izin verir. İplik-yerel değişkene herhangi bir ekstra talimat olmaksızın erişilebildiği durumlarda, adres üretimi montaj operasyonuna katlanacaktır. Örnekleme yoluyla, buradan .../Linux (Ben netlik için, her durumda montajcı direktifleri bir demet kaldırdık) birkaç farklı olası modlarda yukarıda derleme yöntemiyle x86 4.7 gcc olduğunu
# -S -O2 -m32 -fomit-frame-pointer
incval:
incl %gs:[email protected]
ret
# -S -O2 -m64
incval:
incl %fs:[email protected]
ret
# -S -O2 -m32 -fomit-frame-pointer -fpic
incval:
pushl %ebx
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
leal [email protected](,%ebx,1), %eax
call [email protected]
incl (%eax)
popl %ebx
ret
# -S -O2 -m64 -fpic
incval:
.byte 0x66
leaq [email protected](%rip), %rdi
.value 0x6666
rex64
call [email protected]
incl (%rax)
ret
'un dört örneğinin tümü'un x86/OSX için derlenmiş ve x86/Windows için farklı olsa da farklı olacağını anlayın.
1) Neden ''val + = 1;'' yazamıyorsunuz? 2) Bunu, -O2-S ile derleyin ve derleme çıktısını inceleyin; '__thread' değişkenlerine nasıl erişeceğiniz konusunda yanıldığınızı keşfedeceksiniz. – zwol
@Zack Bununla ilgili bir cevap yazabilir misin? – 0x90
val ++, $ 0x1,% gs: 0xfffffffc çevirir, ancak el ile ("movl $ 1,% gs: val") el ile yaptığımda, $ 0x1,% gs: 0x8049f14 movl çevirir. Benim programımda 0xfffffffc adresi nasıl alınır. – Yogi