使用INVOKE传递数组至过程后,为何无法正确写入整数?
问题分析与解决方案
你遇到的核心问题是没搞懂MASM中过程指针参数的正确访问方式,咱们一步步理清楚:
为什么原代码会写入错误地址?
在get_freq PROC, table PTR DWORD的声明里,table是栈帧上的参数变量——它本身存储的才是你传入的freqTable数组的地址。当你写mov table[0], 'b'时,MASM会把这个语句解析为修改table这个栈变量所在的内存(比如[ebp+8],具体位置由栈帧结构决定),而不是去访问table里存储的地址指向的数组。说白了,你现在是在修改过程的参数值,而非数组内容。
正确的解决方法
要访问指针指向的数组,你需要先把table里存储的数组地址加载到寄存器,再通过寄存器间接访问,或者用MASM的指针语法正确解引用。这里给两种实用写法:
方法1:寄存器中转(推荐,符合汇编常规写法)
如果用EBX这类非易失性寄存器(调用约定要求保留原值),记得先保存再恢复:
.data target BYTE "aaaa",0 freqTable DWORD 256 DUP(0) .code get_freq PROC, table:PTR DWORD push ebx ; 保存EBX到栈,遵守调用约定 mov ebx, table ; 把数组地址加载到EBX寄存器 mov [ebx], 'b' ; 向数组第一个DWORD元素写入'b' pop ebx ; 恢复EBX的原值 ret get_freq ENDP main PROC INVOKE get_freq, ADDR freqTable exit main ENDP
如果用EAX这类易失性寄存器(调用约定允许直接修改),可以简化成:
get_freq PROC, table:PTR DWORD mov eax, table ; 把数组地址加载到EAX mov [eax], 'b' ; 写入数组第一个元素 ret get_freq ENDP
额外提示
'b'是ASCII字节值(98),而你的freqTable是DWORD数组,写入后会自动填充为0x00000062,这完全符合频率统计的需求。如果只想写入单字节,也可以改成mov BYTE PTR [ebx], 'b'。
内容的提问来源于stack exchange,提问作者I Like
相关产品推荐
相关产品推荐

