使用带有 Irvine32 库的 MASM 打印数组
Posted
技术标签:
【中文标题】使用带有 Irvine32 库的 MASM 打印数组【英文标题】:Printing an array using MASM with Irvine32 library 【发布时间】:2015-11-11 10:45:31 【问题描述】:我的程序接受 4 个整数,并假设将它们显示给用户。打印值时,我没有得到预期的结果。我正在使用 MASM 和 Kip 的 Irvine32 library
我的代码是:
include irvine32.inc
.data
msg byte "Enter a number",0
arr dword 4 dup(?)
len=($-arr)/4
.code
main PROC
mov edx,offset msg
call writestring
call crlf
mov eax,0
mov ecx,0
.while(ecx<len)
call readdec
mov arr[ecx],eax
inc ecx
.endw
mov ebx,0
mov ecx,0
.while(ecx<len)
mov ebx,arr[ecx]
call writedec
call crlf
inc ecx
.endw
exit
main ENDP
END main
我的程序的示例运行:
Enter a number
1
2
3
4
4
4
4
4
在输入数字 1、2、3 和 4 后,程序应该将这些数字显示给用户。我期望的输出是:
Enter a number
1
2
3
4
1
2
3
4
如果我修改打印数字的循环,以便使用以下代码将要打印的值放在 EAX 而不是 EBX 中:
mov eax,arr[ecx]
call writedec
我最终得到如下无意义的输出值:
Enter a number
1
2
3
4
67305985
262914
1027
4
为什么我的程序会这样,我该如何修改它以获得预期的结果?
【问题讨论】:
是什么让您认为writedec
期望在ebx
中输入?
@Micheal 我在第二个循环中使用了 eax,但它打印了一些非常长的值。所以我改用了ebx。
【参考方案1】:
代码中只有一个真正的问题出现在不同的地方。当您执行以下操作时:
.while(ecx<len)
call readdec
mov arr[ecx],eax
inc ecx
.endw
您必须意识到arr[ecx]
与arr+ecx
相同。 ECX 是添加到 arr 的字节偏移量。问题是 arr 的每个元素都是 32 位(4 字节),因为您将数组声明为:
arr dword 4 dup(?)
您需要做的是将 ECX 乘以每个元素的长度(在本例中为 4 个字节)。您可以通过将 ECX 乘以数组 arr[ecx*4]
= arr+(ecx*4)
中元素的大小来做到这一点。这种形式的scaled addressing 仅支持乘以 32 位代码中的 1、2、4 和 8 的值。你的代码应该是这样的:
.while(ecx<len)
call readdec
mov arr[ecx*4],eax
inc ecx
.endw
调用 writedec 的代码也存在类似问题。同样,writedec 将数字打印在 EAX 中,而不是 EBX 中。这段代码:
.while(ecx<len)
mov ebx,arr[ecx]
call writedec
call crlf
inc ecx
.endw
应该是这样的:
.while(ecx<len)
mov eax,arr[ecx*4]
call writedec
call crlf
inc ecx
.endw
在MASM 中获取数组长度的另一个技巧是使用lengthof
伪操作码。你写的地方:
len=($-arr)/4
你可以使用:
len=lengthof arr
lengthof 将返回 arr 中的元素数。 MASM 考虑到每个元素大小的大小(在本例中为 4,因为您使用 DWORD 元素声明了 arr)。你的做法没有错,我提供了另一种机制。
我强烈建议您学习使用调试器来单步调试您的代码。调试器可以是一个非常宝贵的工具,它可以让您查看代码中的进展情况,并在任何给定时间查看寄存器和内存中的内容。
【讨论】:
以上是关于使用带有 Irvine32 库的 MASM 打印数组的主要内容,如果未能解决你的问题,请参考以下文章
如何将Assembly(irvine masm)中的字符串初始化回null?
将 foo[si] 之类的 16 位地址与 Irvine32 一起使用(在 32 位模式下)?