У меня есть код в NASM (64 бит) в Windows для запуска четырех одновременных потоков (каждый из которых назначен отдельному ядру) на четырехъядерном компьютере с Windows x86-64.
Параметр lpParameter передается в r9 (переменные данных для каждого потока, передаваемого в функцию).Я передаю указатель на 8-элементный внутренний массив (ThreadInfo), который содержит переменные для включения в регистры при входе в функцию (переменные хранятся в регистрах в целях оптимизации).Все четыре потока вызывают одну и ту же функцию.
Проблема в том, что при входе в функцию все данные, передаваемые в массиве ThreadInfo, представляют собой большие (например, 128-битные) отрицательные числа.Массив содержит 64-битные целые числа.Массив доступен только для чтения для каждого из потоков, поэтому ни один поток не может изменить память.Я не понимаю, почему значения должны быть неправильными.Я проверил их в коде создания потока, и они верны, но они возвращают неправильные значения при чтении из вызываемой функции.
Вот тестовый код, показывающий соответствующие части.Показ воспроизводимого примера может быть невозможен из-за значений регистра, но если на этот вопрос невозможно ответить без этого, тогда я могу посмотреть, возможно ли опубликовать полностью воспроизводимую программу.
Init_Cores_fn:
; EACH OF THE CORES CALLS Test_Function AND EXECUTES THE WHOLE PROGRAM.
; WE PASS THE STARTING BYTE (0, 8, 16, 24) AND THE "STRIDE" = NUMBER OF CORES.
; ON RETURN, WE SYNCHRONIZE ANY DATA. ON ENTRY TO EACH CORE, SET THE REGISTERS
; Populate the ThreadInfo array with vars to pass
; ThreadInfo: length, startbyte, stride, vars into registers on entry to each core
mov rdi,ThreadInfo
mov rax,ThreadInfoLength
mov [rdi],rax
mov rax,[stride]
mov [rdi+16],rax ; 8 x number of cores (32 in this example)
; Register Vars
mov [rdi+24],r15
mov [rdi+32],r14
mov [rdi+40],r13
mov [rdi+48],r12
mov [rdi+56],r10
mov rbp,rsp ; preserve caller's stack frame
sub rsp,56 ; Shadow space
; _____
label_0:
mov rdi,ThreadInfo
mov rax,[FirstByte]
mov [rdi+8],rax ; 0, 8, 16, or 24
; _____
; Create Threads
mov rcx,0 ; lpThreadAttributes (Security Attributes)
mov rdx,0 ; dwStackSize
mov r8,Test_Function ; lpStartAddress (function pointer)
mov r9,ThreadInfo ; lpParameter (array of data passed to each core)
mov rax,0
mov [rsp+40],rax ; use default creation flags
mov rax,[ThreadCount]
mov [rsp+32],rax ; ThreadID
call CreateThread
; Move the handle into ThreadHandles array (returned in rax)
mov rdi,ThreadHandles
mov rcx,[FirstByte]
mov [rdi+rcx],rax
mov rax,[FirstByte]
add rax,8
mov [FirstByte],rax
mov rax,[ThreadCount]
add rax,1
mov [ThreadCount],rax
mov rbx,4
cmp rax,rbx
jl label_0
; _____
; Wait
mov rcx,rax ; number of handles
mov rdx,ThreadHandles ; pointer to handles array
mov r8,1 ; wait for all threads to complete
mov r9,1000 ; milliseconds to wait
call WaitForMultipleObjects
; _____
;[ Code HERE to do cleanup if needed after the four threads finish ]
mov rsp,rbp
jmp label_900
; __________________
; The function for all threads to call
Test_Function:
; Populate registers
mov rdi,r9
mov rax,[rdi]
mov r15,[rdi+24]
mov rax,[rdi+8] ; start byte
mov r13,[rdi+40]
mov r12,[rdi+48]
mov r10,[rdi+56]
xor r11,r11
xor r9,r9
pxor xmm15,xmm15
pxor xmm15,xmm14
pxor xmm15,xmm13
Указатель передается в r9, но при входе в Test_Function все значения являются большими (например, 128-битными) отрицательными значениями.Почему?
Спасибо за любую помощь в этом.