更新:我在下面马克·托洛宁的回答的帮助下解决了这个问题。以下是解决方案(但有一件事让我感到困惑):
CA_f1 = (ctypes.c_char_p * len(f1))(*(name.encode() for name in f1))
在关闭优化的情况下,我总是在条目上将rcx存储到内存变量中。稍后在程序中,当我需要在rcx中使用指针时,我从内存中读取它。这适用于单个指针,但不适用于访问下面显示的指针数组Mark Tolonen;也许这是因为它是一个指针数组,而不仅仅是一个指针。如果我在进入时将rcx存储到r15中,它确实可以工作,在程序的下游,它的工作方式如下:
;To access the first char of the first name pair:
xor rax,rax
mov rdx,qword[r15]
movsx eax,BYTE[rdx]
ret
;To access the second char of the second name pair:
mov rdx,qword[r15+8]
movsx eax,BYTE[rdx+1]
这不是问题,因为我通常在寄存器中存储尽可能多的变量;有时寄存器不够,所以我不得不在内存中存储一些寄存器。现在,在处理字符串时,如果是指针数组,我将始终保留r15来保存在rcx中传递的指针。
了解内存位置不工作的原因吗?
我是NASM中字符串处理的新手,正在从ctypes传递字符串。使用以下Python函数从文本文件(Windows.txt)读取字符串数据:
with open(fname, encoding = "utf8") as f1:
for item in f1:
item = item.lstrip()
item = item.rstrip()
return_data.append(item)
return return_data
CA_f1 = (ctypes.c_char_p * len(f1))()
VisualStudio确认它是指向50个名称长的字节字符串的指针,这就是问题所在,我需要的是字节,而不是列表元素。然后我使用以下ctypes语法传递它:
CallName.argtypes = [ctypes.POINTER(ctypes.c_char_p),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double)]
更新:在传递字符串之前,现在我将列表转换为如下字符串:
f1_x = ' '.join(f1)
现在VS显示了一个指向558字节字符串的指针,这是正确的,但我仍然无法读取一个字节。
在我的NASM程序中,我使用以下代码将一个随机字节读入al进行测试:
lea rdi,[rel f1_ptr]
mov rbp,qword [rdi] ; Pointer
xor rax,rax
mov al,byte[rbp+1]
name_array: db "Margaret Swanson"
我可以这样读:
mov rdi,name_array
xor rax,rax
mov al,[rdi]
但不是从传递到dll的指针。
下面是NASM中一个简单、可复制示例的完整代码。在将其传递给NASM之前,我检查了随机字节,它们是我所期望的,所以我认为这不是编码。
[BITS 64]
[default rel]
extern malloc, calloc, realloc, free
global Main_Entry_fn
export Main_Entry_fn
global FreeMem_fn
export FreeMem_fn
section .data align=16
f1_ptr: dq 0
f1_length: dq 0
f2_ptr: dq 0
f2_length: dq 0
data_master_ptr: dq 0
section .text
String_Test_fn:
;______
lea rdi,[rel f1_ptr]
mov rbp,qword [rdi]
xor rax,rax
mov al,byte[rbp+10]
ret
;__________
;Free the memory
FreeMem_fn:
sub rsp,40
call free
add rsp,40
ret
; __________
; Main Entry
Main_Entry_fn:
push rdi
push rbp
mov [f1_ptr],rcx
mov [f2_ptr],rdx
mov [data_master_ptr],r8
lea rdi,[data_master_ptr]
mov rbp,[rdi]
xor rcx,rcx
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [f1_length],rax
add rcx,8
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [f2_length],rax
add rcx,8
call String_Test_fn
pop rbp
pop rdi
ret
更新2:
作为对请求的响应,以下是要使用的ctypes包装器:
def Read_Data():
Dir= "[FULL PATH TO DATA]"
fname1 = Dir + "Random Names.txt"
fname2 = Dir + "Random Phone Numbers.txt"
f1 = Trans_02_Data.StrDataRead(fname1)
f2 = Trans_02_Data.StrDataRead(fname2)
f2_Int = [ int(numeric_string) for numeric_string in f2]
StringTest_asm(f1, f2_Int)
def StringTest_asm(f1,f2):
f1.append("0")
f1_x = ' '.join(f1)
f1_x[0].encode(encoding='UTF-8',errors='strict')
Input_Length_Array = []
Input_Length_Array.append(len(f1))
Input_Length_Array.append(len(f2*8))
length_array_out = (ctypes.c_double * len(Input_Length_Array))(*Input_Length_Array)
CA_f1 = (ctypes.c_char_p * len(f1_x))() #due to SO research
CA_f2 = (ctypes.c_double * len(f2))(*f2)
hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/StringTest/StringTest.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_char_p),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double)]
CallName.restype = ctypes.c_int64
Free_Mem = hDLL.FreeMem_fn
Free_Mem.argtypes = [ctypes.POINTER(ctypes.c_double)]
Free_Mem.restype = ctypes.c_int64
start_time = timeit.default_timer()
ret_ptr = CallName(CA_f1,CA_f2,length_array_out)
abc = 1 #Check the value of the ret_ptr, should be non-zero