Passing arrays to NASM DLL, pointer value gets reset to zero

孤街醉人 提交于 2020-01-06 05:16:11

问题


I am passing three arrays of doubles from Python (3.6.2) into a DLL written in 64-bit NASM (Windows) using CTypes. The pointers to the arrays are in rcx, rdx, r8 and r9.

On entry, I extract the pointers into three separate arrays, called a_in_data, b_in_data, and c_in_data. The elements of those arrays are (1) pointer (2) data type and (3) length.

In the area preceded by "Test #1" in the code below we check the value at b_in_data[0] and we get a valid pointer (just remove the comment symbols and jump to the end).

In the area preceded by "Test #2" we check the value at b_in_data[0] and we get zero. The array b_in_data[0] has not been changed by this point, but somehow it gets set to back zero.

The same happens in the block following for c_in_data. For some reason, the first code block (headed by "Extract data type and length") zeroes out the first value in b_in_data and c_in_data.

I have identified the line that is causing the problem; it's followed by the comment "THIS LINE IS THE PROBLEM, BUT IT'S NOT CLEAR WHY."

The Python code is long, but if it helps to reproduce this, please ask and I will post it. Here is the NASM code:

; Header Section
[BITS 64]

export TryThemAll

section .data
a_in_data: dd 0, 0, 0
b_in_data: dd 0, 0, 0
c_in_data: dd 0, 0, 0
out_array_pointer: dd 0
call_var_length: dd 0

section .text
finit

; _________________

TryThemAll:

push rdi
push rbp
push qword rcx
pop qword [a_in_data]
push qword rdx
pop qword [b_in_data]
push qword r8
pop qword [c_in_data]
push qword r9
pop qword [out_array_pointer]

; Test #1
; Now the value at b_in_data[0] is the pointer we just extracted from rdx
;mov rbp,b_in_data
;mov rax,qword [rbp]
;jmp out_here

;_______

; Extract data type and length
mov rdi,[out_array_pointer]
mov rbp,a_in_data
movsd xmm0,qword [rdi] ;Data type for a_in
cvttsd2si rax,xmm0
mov [rbp+8],rax ; THIS LINE IS THE PROBLEM, BUT IT'S NOT CLEAR WHY
movsd xmm0,qword [rdi+8] ;Length for a_in
cvttsd2si rax,xmm0
mov [rbp+16],rax

mov rbp,b_in_data
movsd xmm0,qword [rdi+16] ;Data type for b_in
cvttsd2si rax,xmm0
mov [rbp+8],rax
movsd xmm0,qword [rdi+24] ;Length for b_in
cvttsd2si rax,xmm0
mov [rbp+16],rax

; Test #2
; Now the value at [0] in b_in_data is zero !!!
mov rbp,b_in_data
mov rax,qword [rbp]
jmp out_here

mov rbp,c_in_data
movsd xmm0,qword [rdi+32] ;Data type for c_in
cvttsd2si rax,xmm0
mov [rbp+8],rax
movsd xmm0,qword [rdi+40] ;Length for c_in
cvttsd2si rax,xmm0
mov [rbp+16],rax

;_______

out_here:

pop rbp
pop rdi
ret

Thanks in advance for any help.


回答1:


The solution to this problem was quite simple. The three arrays a_in_data, b_in_data and c_in_data were defined contiguously in the .data section as "dd" but should have been defined as "dq" to occupy eight bytes per element instead of four. Naturally successive writes had the effect of overstoring adjacent values.

I recently switched from 32-bit MASM to 64-bit NASM and I'm still getting used to NASM syntax and 64-bit assembly programming, so I'm still making some elementary mistakes.

Thanks, Peter, for the time you took on this. You made some other interesting points. For example, I've switched to using lea (load effective address) instead of moving the pointer to rbp (e.g., mov rbp,b_in_data).

Thanks again, and thanks to Michael Petch for adding the other tags.

BTW, these data are all converted to 64-bit integers, so the struc is not necessary -- they are not mixed types.



来源:https://stackoverflow.com/questions/48373312/passing-arrays-to-nasm-dll-pointer-value-gets-reset-to-zero

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!