如何将寄存器放入 MASM 中的数组索引中?
How do I put a register into an array index in MASM?
我在 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
在你的 C++ 代码中
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] = { '[=10=]' };
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;
}
在你的汇编代码中
- 您通过
mov ebx,[ebp+8]
将 "address of first array element" 存储到 ebx
,因此 arr
的地址将在那里。
不幸的是,它被 add ebx, 4
和 inc ebx
. 摧毁了
- "put edx into the next array index" 不,
[ebp + edi]
不是下一个数组索引,它正在破坏堆栈上的数据。非常糟糕。
- 如果
char
的大小是 1 个字节,请不要向 "find next index" 添加 4 个字节。
你的代码应该是这样的(对不起,这是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;
.
您有 ebx
中第一个数组元素的地址,edi
是您的循环计数器。所以 mov [ebx + edi], edx
会将 edx
存储到 arr[edi]
.
另请注意,您的循环条件是错误的(您的 cmp
正在将元素数量与数组的起始地址进行比较。)
尽可能避免div
。除以二,右移一。 div
非常慢(比 shift 慢 10 到 30 倍)。
顺便说一句,因为你可以选择使用哪些寄存器(ABI 说你可以在没有 saving/restoring 的情况下进行破坏),edi
用于 "destination" 指针(即当它不需要任何额外指令时),而 esi
用作 "source" 指针。
说到 ABI,您需要在使用它的函数中 save/restore ebx
,与 ebp
相同。它在函数调用中保持其值(因为您调用的任何符合 ABI 的函数都会保留它)。我忘记了在 32 位 ABI 中还有哪些其他寄存器是被调用者保存的。您可以查看 https://whosebug.com/tags/x86/info 中的有用链接。 32 位已过时; 64 位具有更高效的 ABI,并将 SSE2 作为基线的一部分。
我在 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
在你的 C++ 代码中
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] = { '[=10=]' };
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;
}
在你的汇编代码中
- 您通过
mov ebx,[ebp+8]
将 "address of first array element" 存储到ebx
,因此arr
的地址将在那里。 不幸的是,它被add ebx, 4
和inc ebx
. 摧毁了
- "put edx into the next array index" 不,
[ebp + edi]
不是下一个数组索引,它正在破坏堆栈上的数据。非常糟糕。 - 如果
char
的大小是 1 个字节,请不要向 "find next index" 添加 4 个字节。
你的代码应该是这样的(对不起,这是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;
.
您有 ebx
中第一个数组元素的地址,edi
是您的循环计数器。所以 mov [ebx + edi], edx
会将 edx
存储到 arr[edi]
.
另请注意,您的循环条件是错误的(您的 cmp
正在将元素数量与数组的起始地址进行比较。)
尽可能避免div
。除以二,右移一。 div
非常慢(比 shift 慢 10 到 30 倍)。
顺便说一句,因为你可以选择使用哪些寄存器(ABI 说你可以在没有 saving/restoring 的情况下进行破坏),edi
用于 "destination" 指针(即当它不需要任何额外指令时),而 esi
用作 "source" 指针。
说到 ABI,您需要在使用它的函数中 save/restore ebx
,与 ebp
相同。它在函数调用中保持其值(因为您调用的任何符合 ABI 的函数都会保留它)。我忘记了在 32 位 ABI 中还有哪些其他寄存器是被调用者保存的。您可以查看 https://whosebug.com/tags/x86/info 中的有用链接。 32 位已过时; 64 位具有更高效的 ABI,并将 SSE2 作为基线的一部分。