【问题标题】:Trouble inserting things into an array in assembly在程序集中将东西插入数组时遇到问题
【发布时间】:2015-11-12 20:27:43
【问题描述】:

我目前正在尝试学习汇编,我的任务之一是获取用户输入的整数并将这些数字插入到数组中。一旦数组有 7 个整数,我将遍历数组并打印出数字。但是,我目前坚持如何将数字插入数组。这是我现在的代码:

.DATA

inputIntMessage BYTE "Enter an integer: ", 0
inputStringMessage BYTE "Enter a string: ", 0


intArray DWORD 0,0,0,0,0,0,0
intCounter DWORD 0
user_input DWORD ?

.CODE

main PROC

mov eax, intCounter
mov edx, 0

top: 
    cmp eax, 7      
    je final1
    jl L1

L1: intInput inputIntMessage, user_input
    mov ebx, user_input
    mov intArray[edx], ebx ;This is where I think the problem is.
    add edx, 4
    inc eax
    jmp top

final1:

mov ecx, 0
mov edx, 0
printarrayloop: 
            cmp edx,7
            jl L2
            je next
L2: intOutput intArray[ecx] 
    add ecx, 4
    inc edx
next:

next: 直接进入下一个问题;与此插入数组问题无关。我的想法是我应该使用数组的偏移量,所以我可以访问数组中每个元素的地址并直接更改它,但我不知道如何。有人能指出我正确的方向吗?

编辑:当我运行程序时,窗口提示用户输入一个整数 7 次(这是预期的),然后打印出用户输入的第一个数字。但是,窗口应该打印出用户输入的所有数字。

【问题讨论】:

  • 你有没有在调试器中单步执行代码来观察会发生什么?
  • jl L1; L1: 的意义何在? intInput 宏是否保留 eax 中的内容?
  • 是的,但不幸的是我无法从中获得任何信息。所有变量都正确递增,所有寄存器都应该是。
  • @500-InternalServerError 实际上,我只是注意到一个错误。 jl L1 如果 eax 小于 7 应该跳转到 L1 (即代码还没有执行 7 次,所以它将继续执行直到它运行 7 次。)你的意思是宏保留 @987654326 中的内容@?
  • 运行程序时会发生什么? jl L1 L1: mov...` 只是删除jl L1jl L2 je next 可以简化为 jge next 。而不是做intArraty[edx] 然后add edx, 4 您可以删除add edx,4 并通过将intArray[edx] 更改为intArray[edx*4] 来使用缩放索引寻址(类似的事情适用于您的输出)。这些更改不会修复错误,但会使代码更简洁。

标签: arrays assembly x86 masm


【解决方案1】:

您的代码只打印一个数字的主要原因是因为显示数字数组的代码是这样做的:

mov ecx, 0
mov edx, 0
printarrayloop: 
    cmp edx,7
    jl L2
    je next
L2: intOutput intArray[ecx] 
    add ecx, 4
    inc edx
next:

缺少的是您在显示第一个数字后不继续循环。您需要跳回 printarrayloop 来处理下一个数字。在inc edx下面添加这个:

     jmp printarrayloop

您可能还需要考虑其他一些事情。在这段代码中:

top: 
    cmp eax, 7      
    je final1
    jl L1

L1: intInput inputIntMessage, user_input
[snip]
final1:

你是cmp eax, 7。如果相等,则跳出。如果它小于那么你只是分支到标签L1 无论如何。您可以通过删除无关的 jl L1 分支和标签来修改该代码。所以你会有这个:

top: 
    cmp eax, 7      
    je final1    
    intInput inputIntMessage, user_input

在这段代码中有一些额外的指令可以去掉:

mov ecx, 0
mov edx, 0
printarrayloop: 
    cmp edx,7
    jl L2
    je next
L2: intOutput intArray[ecx] 
    add ecx, 4
    inc edx
    jmp printarrayloop
next:

类似于我之前使用cmp edx,7EDX 与7 进行比较的评论。您可以简单地说,在比较它是否等于 7 之后,您跳出循环到 next 。如果它小于 7,它将继续并打印出数字。所以你的代码可能看起来像这样:

mov ecx, 0
mov edx, 0
printarrayloop: 
    cmp edx,7
    je next
    intOutput intArray[ecx] 
    add ecx, 4
    inc edx
    jmp printarrayloop
next:

x86 32 位代码具有缩放寻址模式(带位移)。您可以在此摘要here 和更详细的描述here 中找到所有寻址模式。

在进行寻址时,您可以使用比例因子(将寄存器乘以 1、2、4 或 8)。您的代码如下所示:

    mov intArray[edx], ebx 
    add edx, 4

EDX 指向您希望显示的元素编号,将其乘以 4 将说明 DWORD 的大小为 4 个字节。所以你可以删除add edx, 4并将访问数组的代码更改为:

    mov intArray[edx*4], ebx 

intArray[edx*4] 是等同于intArray+(edx*4) 的地址

您可以在输出时进行类似的更改。删除这一行:

    add ecx, 4

并使用缩放寻址:

    intOutput intArray[ecx*4]

【讨论】:

  • 非常感谢。答案很广泛!
猜你喜欢
  • 2023-03-17
  • 2016-12-20
  • 2013-08-06
  • 1970-01-01
  • 1970-01-01
  • 2020-08-29
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
相关资源
最近更新 更多