NASM如何返回指针数组?

时间:2018-03-13 21:48:07

标签: python arrays nasm x86-64 ctypes

我从ctypes打电话给NASM dll。在我的NASM DLL代码中,我使用malloc创建了三个数组。他们的指针分配给final1_ptr,final2_ptr和final3_ptr。如果我单独返回任何指针,我会得到正确的结果。

但我想返回所有三个指针的数组。为此,我还在.data部分初始化了一个数组:Return_Pointer_Array:dq 0,0,0。

最后我用这种方式指定指针:

mov rdi,Return_Pointer_Array
mov rax,qword[final1_ptr]
mov qword [rdi],rax
mov rax,qword[final2_ptr]
mov qword [rdi+8],rax
mov rax,qword[final3_ptr]
mov qword [rdi+16],rax
mov rax,rdi
ret

但是,ctypes得到的是一个由三个非常小的小数组成的数组,而不是有效的指针地址。

实际的程序列表很长,所以我希望上面的代码足以理解这个问题。

非常感谢您的帮助。

编辑:如果我在不指定任何值的情况下返回Return_Pointer_Array,则返回double(浮点)值。数组被初始化为整数,所以我不明白为什么它在初始化为dq 0,0,0时默认为浮点数。

编辑#2:编辑#2: 根据请求,这是Python代码:

def Test_Data_Read():

#Note:  in production, X is a list of 50,000 random floats read from file; 
#For simplicity, I have reduced it to a short simple list:  

X = [11.0,1.0,2.0,7.0,4.0,4.0,4.0,6.0,7.0,6.0,11.0,4.0,10.0,7.0,8.0,4.0,9.0,4.0,5.0,3.0,4.0,1.0,2.0,5.0,3.0,5.0,11.0,10.0,11.0,9.0,3.0,12.0]

PyGram_Test_01_asm(X)

#__________

def PyGram_Test_01_asm(X):

Input_Length_Array = []
Input_Length_Array.append(len(X)*8)

CA_X = (ctypes.c_double * len(X))(*X)
length_array_out = (ctypes.c_double * len(Input_Length_Array))(*Input_Length_Array)

hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/Nested_For_Loops/Nested_For_Loops.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double)]
CallName.restype = ctypes.POINTER(ctypes.c_double)

start_time = timeit.default_timer()

ret_ptr = CallName(CA_X,length_array_out)

a = ret_ptr[:3]

以下是整个NASM列表(有时候最小和完整的彼此不一致)

; Header Section
[BITS 64]

[default rel]

export Main_Entry_fn

extern malloc, realloc, free

section .data align=16
out_array_pointer: dq 0
call_var_length: dq 0
c_square: dq 0
final1_ptr: dq 0
final1_ctr: dq 0
final2_ptr: dq 0
final2_ctr: dq 0
final3_ptr: dq 0
final3_ctr: dq 0
float_temp_var: dq 0.0
temp_math_var: dq 0
Bool_0: dq 0.0
Bool_1: dq 1.0
data_master_ptr: dq 0
initial_dynamic_length: dq 0
X_ptr: dq 0
X_ctr: dq 0
X: dq 0
n: dq 0
i: dq 0
a: dq 0.0
range_loop_start_a: dq 0
range_loop_end_a: dq 0
b: dq 0.0
range_loop_start_b: dq 0
range_loop_end_b: dq 0
c: dq 0
X_length: dq 0
Input_Length_Array: dq 0,
Return_Pointer_Array: dq 0, 0, 0

section .text

PyGram_Test_01_fn:
xor rcx,rcx
mov [X_ctr],rcx
label_401:
lea rdi,[rel X_ptr]
mov rbp,qword [rdi]
mov rcx,[X_ctr]
cmp rcx,[X_length]
jge exit_label_for_PyGram_Test_01_fn
movsd xmm0,[rbp+rcx]
movsd [n],xmm0
add rcx,8
mov [X_ctr],rcx
movsd xmm0,qword[n]
cvttsd2si rax,xmm0
mov [n],rax
mov rax,[n]
mov rdx,1
add rax,rdx
mov [range_loop_end_a],rax
mov rax,1
sub rax,1
mov [range_loop_start_a],rax
mov [a],rax
label_801:
mov rcx,[a]
inc rcx
cmp rcx,[range_loop_end_a]
jge label_401
mov [a],rcx
mov rax,[a]
sub rax,1
mov [range_loop_start_b],rax
mov [b],rax
mov rax,[n]
mov [range_loop_end_b],rax
label_1201:
mov rcx,[b]
inc rcx
cmp rcx,[range_loop_end_b]
jge label_801
mov [b],rcx
mov rax,[a]
mov r8,[a]
xor rcx,rcx
add rcx,1
Exponent_Label_0:
mul r8
inc rcx
mov rdx,2
cmp rcx,rdx
jl Exponent_Label_0
mov[temp_math_var],rax
mov rax,[b]
mov r8,[b]
xor rcx,rcx
add rcx,1
Exponent_Label_1:
mul r8
inc rcx
mov rdx,2
cmp rcx,rdx
jl Exponent_Label_1
mov rdx,rax
mov rax,[temp_math_var]
add rax,rdx
mov [c_square],rax
mov rax,[c_square]
mov rax,[c_square]
cvtsi2sd xmm1,rax
sqrtsd xmm0,xmm1
cvttsd2si rax,xmm0
mov [c],rax
label_1601:
mov rax,[c]
mov rax,[c]
mov r8,[c]
xor rcx,rcx
add rcx,1
Exponent_Label_2:
mul r8
inc rcx
mov rdx,2
cmp rcx,rdx
jl Exponent_Label_2
mov [temp_math_var],rax
mov rax,[c_square]
mov rdx,[temp_math_var]
sub rax,rdx
mov rdx,0
cmp rax,rdx
jne label_1201
mov rdi,[final1_ptr]
mov rcx,[final1_ctr]
mov rax,[a]
cvtsi2sd xmm0,rax
movsd [rdi + rcx],xmm0
add rcx,8
mov [final1_ctr],rcx
mov rdi,[final2_ptr]
mov rcx,[final2_ctr]
mov rax,[b]
cvtsi2sd xmm0,rax
movsd [rdi + rcx],xmm0
add rcx,8
mov [final2_ctr],rcx
mov rdi,[final3_ptr]
mov rcx,[final3_ctr]
mov rax,[c]
cvtsi2sd xmm0,rax
movsd [rdi + rcx],xmm0
add rcx,8
mov [final3_ctr],rcx
jmp label_1201
label_900:
exit_label_for_PyGram_Test_01_fn:
mov rdi,Return_Pointer_Array
mov rax,qword[final1_ptr]
mov qword [rdi],rax
mov rax,qword[final2_ptr]
mov qword [rdi+8],rax
mov rax,qword[final3_ptr]
mov qword [rdi+16],rax
mov rax,rdi
ret

; __________
; Main Entry

Main_Entry_fn:
push rdi
push rbp
mov [X_ptr],rcx
mov [data_master_ptr],rdx
; Now assign lengths
lea rdi,[data_master_ptr]
mov rbp,[rdi]
xor rcx,rcx
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [X_length],rax
add rcx,8
; __________
; malloc for dynamic arrays
lea rdi,[data_master_ptr]
mov rbp,[rdi]
movsd xmm0,qword[rbp]
cvttsd2si rax,xmm0
mov [initial_dynamic_length],rax
mov rax,3529984
mov [initial_dynamic_length],rax
mov rcx,qword[initial_dynamic_length] ; Initial size
xor rax,rax
sub rsp,40
call malloc
mov qword [final1_ptr],rax
add rsp,40
mov rcx,qword[initial_dynamic_length] ; Initial size
xor rax,rax
sub rsp,40
call malloc
mov qword [final2_ptr],rax
add rsp,40
mov rcx,qword[initial_dynamic_length] ; Initial size
xor rax,rax
sub rsp,40
call malloc
mov qword [final3_ptr],rax
add rsp,40
; __________
call PyGram_Test_01_fn
exit_label_for_Main_Entry_fn:
pop rbp
pop rdi
ret

def PyGram_Test_01(X):

final1, final2, final3 = [],[],[]

这是汇编程序的Python源代码:

for i, n in enumerate(X):
    n = int(n)
    for a in range(1,n+1):
        for b in range(a,n):
            c_square = a**2 + b**2
            c = int(sqrt(c_square))

            if ((c_square - c**2) == 0):
                final1.append(a)
                final2.append(b)
                final3.append(c)

1 个答案:

答案 0 :(得分:1)

我将此作为答案发布,因为其他人可能需要此信息。在Michael Petch(上图)的帮助下,我解决了这个问题。

要将指针数组从dll返回到ctypes:

  1. 在dll中声明一个数组(对于NASM,它在.data部分声明,例如Return_Pointer_Array:dq 0,0,0)。

  2. 退出时,指定指向数组的指针(对于汇编程序;在C中,指定使用C赋值):

    mov rdi,Return_Pointer_Array
    mov rax,qword[final1_ptr]
    mov [rdi],rax
    mov rax,qword[final2_ptr]
    mov [rdi+8],rax
    mov rax,qword[final3_ptr]
    mov [rdi+16],rax
    mov rax,rdi
    
  3. 将返回类型设置为CallName.restype = ctypes.POINTER(ctypes.c_int64)。

  4. 转换每个返回的指针并将数据转换为Python数组(在此示例中,我事先知道每个数组中有多少个元素;对于动态数组,长度可以传递回返回数组的一个元素):

    ret_ptr = CallName(CA_X,length_array_out)
    a = ret_ptr[:3]
    n1 = ctypes.cast(a[0], ctypes.POINTER(ctypes.c_double))
    x1 = n1[:50000]
    n2 = ctypes.cast(a[1], ctypes.POINTER(ctypes.c_double))
    x2 = n2[:50000]
    n3 = ctypes.cast(a[2], ctypes.POINTER(ctypes.c_double))
    x3 = n3[:50000]
    
  5. 或者,将返回类型设置为CallName.restype = ctypes.POINTER(ctypes.POINTER(ctypes.c_double)),如Michael Petch所述,并提取如下值:

        ret_ptr = CallName(CA_X,length_array_out)
        a = ret_ptr[:3]
        n1 = a[0]
        x1 = n1[:50000]
        etc