使用带有 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?

ReadConsoleInputA 引发访问冲突

使用 MASM32 随机化装配中的数字

将 foo[si] 之类的 16 位地址与 Irvine32 一起使用(在 32 位模式下)?

如何使用 Irvine32 WriteFloat 而非 printf 显示舍入为 .001 的浮点数

定义和调用接收不同数据类型的宏时指令操作数大小错误。使用 masm32