我在MASM中使用数组非常困难。我不明白如何将寄存器的值放入数组的索引中。我似乎无法找到arr [i]的位置。我错过了什么或者我错了什么? 谢谢你的时间!
C ++代码:
#include <iostream>
using namespace std;
extern"C"
{
char intToBinary(char *, int, int);
}
int main()
{
const int SIZE = 16;
char arr[SIZE] = { '/0' };
cout << "What integer do you want converted?" << endl;
cin >> decimal;
char value = intToBinary(arr, SIZE, decimal);
return 0;
}
汇编代码:
.686
.model flat
.code
_intToBinary PROC ; named _test because C automatically prepends an underscode, it is needed to interoperate
push ebp
mov ebp,esp ; stack pointer to ebp
mov ebx,[ebp+8] ; address of first array element
mov ecx,[ebp+12] ; number of elements in array
mov edx, 0 ;has to be 0 to check remainder
mov esi, 2 ;the new divisor
mov edi, 12
LoopMe:
add ebx, 4
xor edx, edx ;keep this 0 at all divisions
div esi ;divide eax by 2
inc ebx ;increment by 1
mov [ebp + edi], edx ;put edx into the next array index
add edi, 4 ;add 4 bytes to find next index
cmp ecx, ebx ;compare iterator to number of elements (16)
jg LoopMe
pop ebp ;return
ret
_intToBinary ENDP
END
答案 0 :(得分:1)
decimal
未定义。'/0'
是无效的字符文字。使用\
而不是/
在C ++中编写转义序列。value
未使用。您的代码应该是这样的:
#include <iostream>
using namespace std;
extern"C"
{
char intToBinary(char *, int, int);
}
int main()
{
const int SIZE = 16;
char arr[SIZE] = { '\0' };
int decimal;
cout << "What integer do you want converted?" << endl;
cin >> decimal;
intToBinary(arr, SIZE, decimal);
for (int i = SIZE - 1; i >= 0; i--) cout << arr[i];
cout << endl;
return 0;
}
ebx
到mov ebx,[ebp+8]
,arr
的地址就在那里。
不幸的是,它被add ebx, 4
和inc ebx
销毁。[ebp + edi]
不是下一个数组索引,它是堆栈上令人讨厌的数据。这非常糟糕。char
的大小是1个字节。你的代码应该是这样的(对不起,这是nasm代码,因为我对masm不熟悉):
bits 32
global _intToBinary
_intToBinary:
push ebp
mov ebp, esp ; stack pointer to ebp
push esi ; save this register before breaking in the code
push edi ; save this, too
push ebx ; save this, too
mov ebx, [ebp + 8] ; address of first array element
mov ecx, [ebp + 12] ; number of elements in array
mov eax, [ebp + 16] ; the number to convert
xor edi, edi ; the index of array to store
mov esi, 2 ; the new divisor
LoopMe:
xor edx, edx ; keep this 0 at all divisions
div esi ; divide eax by 2
add dl, 48 ; convert the number in dl to a character representing it
mov [ebx + edi], dl ; put dl into the next array index
inc edi ; add 1 byte to find next index
cmp ecx, edi ; compare iterator to number of elements
jg LoopMe
xor eax, eax ; return 0
pop ebx ; restore the saved register
pop edi ; restore this, too
pop esi ; restore this, too
mov esp, ebp ; restore stack pointer
pop ebp
ret
请注意,此代码将以相反的顺序存储二进制文本,因此我编写了C ++代码以从后到前打印它们。
另请注意,arr
中没有终止空字符,因此请勿执行cout << arr;
。
答案 1 :(得分:1)
您拥有ebx
中第一个数组元素的地址,而edi
是您的循环计数器。因此mov [ebx + edi], edx
会将edx
存储到arr[edi]
。
另请注意,您的循环条件错误(您的cmp
正在将元素数量与数组的起始地址进行比较。)
尽可能避免使用div
。除以2,右移一。 div
非常慢(比移位慢10到30倍)。
顺便说一下,既然您可以选择使用哪些寄存器(ABI说允许您在不保存/恢复的情况下使用哪些寄存器),edi
按惯例用于“目标”指针(即,当它不需要任何额外的指令时),而esi
被用作“源”指针。
说到ABI,您需要在使用它的函数中保存/恢复ebx
,与ebp
相同。它在函数调用中保持其值(因为您调用的任何符合ABI的函数都会保留它)。我忘记了在32位ABI中被调用者保存的其他寄存器。您可以查看https://stackoverflow.com/tags/x86/info中的有用链接。 32位已经过时; 64位具有更高效的ABI,并且包括SSE2作为基线的一部分。