Base64 汇编程序填充数组错误“操作数不同大小”Visual Studio
Posted
技术标签:
【中文标题】Base64 汇编程序填充数组错误“操作数不同大小”Visual Studio【英文标题】:Base64 Assembler Fill Array Error "Operands different sizes" Visual Studio 【发布时间】:2015-11-02 22:02:48 【问题描述】:我试图在 Visual Studio 的内联汇编器中制作 Base64Encode。
我有这个功能
char* Base64Encode(char* data, int len)
// Tabelle mit den Zeichen für die Codierung
const char* encodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//
char* result;
if (len > 0) // sonst gibt es nichts zu tun ...
int encodedLength = ((len + 2) / 3) * 4; // effektiv die Ganzzahlfassung von ceil(length/3)*4
result = new char[encodedLength+1]; // +1 wg. Null-Terminierung
_asm
mov esi,data
mov edi,encodeTable
xor eax, eax
// get 3 bytes
mov ah, byte ptr[esi]
mov al, byte ptr[esi+1]
shl eax,16
mov ah, byte ptr[esi+2]
//
mov edx,eax
shl eax,6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov [result],bl
//
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov[result+1], bl
//manipulate in edx bitset3
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov[result+2], bl
//manipulate in edx bitset4
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov[result+3], bl
else
result = "";
return result;
编码工作正常,我在 bl 中总是有正确的字母,但输出不起作用(结果数组没有用字母填充,我收到操作数大小不同的错误,我只被允许在 __asm 函数中进行更改)。
有人可以帮助我如何用我在 bl 中得到的字母填充结果数组吗?如果我注释掉所有结果行,调试总是会在 bl 中显示正确的字母。
编辑:
当我使用字节指针时,结果数组中什么也没有。
有什么想法吗?
EDIT2:
【问题讨论】:
单步执行汇编代码有什么建议? ***.com/questions/14905769/… 不确定这是否是你的意思,在edit2中你看到bl中有一个A,下一步它应该在结果数组中,但结果数组只是0'/0 ' 考虑一下。mov [result],bl
(最好写成mov byte ptr [result],bl
将bl
的内容移动到result
但result
实际上是一个指向字符串的指针(由new
返回)。你缺少一个级别间接。您实际上更改了 pointer 本身,而不是 result 中包含的指针处的数据。
那么您需要在开始时获取变量 result 的 contents(这将是 new
返回的指针)你的 asm 块。将该地址移动到带有类似 mov ecx, dword ptr [result]
的寄存器(例如ecx
)中。 ECX 现在应该是您实际缓冲区的指针。现在,无论您在 asm 块中使用 result
的任何位置,都将其更改为 ecx
。所以mov [result],bl
会变成mov byte ptr [ecx],bl
,mov[result+1], bl
会变成mov byte ptr [ecx+1], bl
等等。
这完全是一个不同的问题。您可以选择像EDX
这样的未使用寄存器作为循环变量。例如,您可以执行mov byte ptr [ecx + edx], bl
、mov byte ptr [ecx + edx + 3], bl
之类的操作。最后一个是基于索引加位移寻址。
【参考方案1】:
您的代码中的问题是间接问题。您可以在 C++ 代码中像这样定义和初始化变量 result
:
char* result;
result = new char[encodedLength+1];
result
是一个内存位置,它保存指向new
返回的字符数组的指针。 result
不是存储数据的内存位置,而是包含指向该数据区域的指针。然后,您可以像这样在 ASM 块中访问它:
mov [result],bl
编译器/汇编器(MASM) 在说操作数不同大小 时警告说存在操作数不匹配。它知道result
是一个32 位指针(不是单个字符)的位置。由于result
是包含指针的地址,因此上面的代码会将bl
的内容移动到内存位置result
。这会改变指针(由new
返回)而不是result
指向的内容。
你需要在这里处理间接性。您想要获取存储在result
中的地址并将其用作内存寻址的 base。您可以选择一个可用的寄存器,如 ECX 和 MOV 将result
的内容放入其中。您可以在 ASM 块的顶部使用类似的东西来做到这一点:
mov ecx, dword ptr [result]
这会在内存位置result
中获取 32 位(dword)值并将其存储在 ECX 中。现在我们有了字符缓冲区开头的内存位置,我们现在可以修改 ASM 块中result
的所有引用并将其更改为 ECX。例子:
mov [result],bl
会变成:
mov byte ptr [ecx],bl
和
mov[result+1], bl
会变成:
mov byte ptr [ecx+1], bl
第二个例子叫做base plus displacement (or offset) addressing。该链接还描述了 x86 上的所有寻址模式。如果您使用的是 16 位代码(您不是),则可用于基址和索引的寄存器选择有一些额外的限制。
user3144770 还指出你没有终止你的字符串(你只为它分配了空间),所以在你的 ASM 底部阻止你应该可能使用类似的东西:
mov byte ptr[ecx+4], 0
通过上面的更改,您的代码可能如下所示:
char* Base64Encode(char* data, int len)
// Tabelle mit den Zeichen für die Codierung
const char* encodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//
char* result;
if (len > 0) // sonst gibt es nichts zu tun ...
int encodedLength = ((len + 2) / 3) * 4; // effektiv die Ganzzahlfassung von ceil(length/3)*4
result = new char[encodedLength + 1]; // +1 wg. Null-Terminierung
_asm
mov esi, data
mov edi, encodeTable
mov ecx, dword ptr [result]
xor eax, eax
// get 3 bytes
mov ah, byte ptr[esi]
mov al, byte ptr[esi + 1]
shl eax, 16
mov ah, byte ptr[esi + 2]
//
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov byte ptr [ecx], bl
//
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov byte ptr [ecx + edx + 1], bl
//manipulate in edx bitset3
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov byte ptr [ecx + 2], bl
//manipulate in edx bitset4
mov edx, eax
shl eax, 6
shr edx, 26
mov bl, byte ptr[edi + edx]
mov byte ptr [ecx + 3], bl
mov byte ptr[ecx + 4], 0
else
result = "";
return result;
【讨论】:
【参考方案2】:也许写byte ptr
就够了
mov bl, byte ptr[edi + edx]
mov byte ptr[result], bl
此外,您实际上并没有执行空终止。 (+1 wg. Null-Terminierung)
mov byte ptr[result+4], 0
【讨论】:
我用过,然后我什么也没得到(编辑我的帖子)有什么想法吗?以上是关于Base64 汇编程序填充数组错误“操作数不同大小”Visual Studio的主要内容,如果未能解决你的问题,请参考以下文章
如果输入长度不能被 3 整除,为啥 base64 编码需要填充?
注册许可证出现“输入的不是有效的 Base-64 字符串,因为它包含非 Base-64 字符两个以上的填充字符,或者填充字符间包含非空白字符”