assembly 汇编MASM -以正确的方式打印动态数组并将其保存在堆中

wa7juj8i  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(132)

我写了一个简单的程序,它获取一个数组长度,通过使用esp递减来填充数组(所以在堆栈上),然后打印数组。我的代码如下:

.686
.xmm
.model flat, C
OPTION CaseMap:None

include ../masm32/libs/windows.inc
include ../masm32/libs/kernel32.inc
include ../masm32/libs/user32.inc
include ../masm32/libs/msvcrt.inc
include ../masm32/libs/masm32.inc

EXTERN printf:PROC
EXTERN scanf:PROC

.data
    str_insert_array_length db  "Insert Array Length: ",0
    str_insert_value    db  10,"Insert Value: ",0
    str_input_format    db  "%d",0
    str_format_print    db  "%d",10,0

    input_length   DWORD    0
    input_value    DWORD    0

.code

main PROC
    push ebp
    mov ebp,esp

    push offset str_insert_array_length
    call printf
    add esp,4

    push offset input_length
    push offset str_input_format
    call scanf
    add esp,8
    
    mov edi,[input_length]

array_input:
    push offset str_insert_value
    call printf
    add esp,4

    push offset input_value
    push offset str_input_format
    call scanf
    add esp,8

    mov eax, [input_value]
    push eax

    dec edi
    jnz array_input

    mov edi,[input_length]
    sub esp,4
print_array:
    mov edx,[esp+4*edi]
    push edx
    push offset str_format_print
    call printf
    add esp,8
    dec edi
    jnz print_array

    add esp,4

    pop ebp
    invoke ExitProcess,0
main ENDP
    end

正如您在“print_array”部分之前所看到的,我需要将esp减去4,因为否则我会将当前返回地址打印为数组的第一个元素(因为它将是“esp+20”,而数组从“esp+16”开始)而不是打印的最后一个元素。在部分之后,我向esp添加4以使其再次到达正确的位置。这是打印数组的正确方法吗?还是有另一种方法代替了代码部分之前/之后的sub/add esp by 4?
我知道我需要声明一个变量,但是这个变量应该有动态的长度,因为数组的长度是动态的,所以我不知道如何得到这个变量:/

0lvr5msh

0lvr5msh1#

正如您在“print_array”部分之前所看到的,我需要将esp减去4,因为否则我会将当前返回地址打印为数组的第一个元素(因为它将是“esp+20”,而数组从“esp+16”开始),而不是打印的最后一个元素。
你的偏移量告诉我你为数组输入了5个数字。你的堆栈看起来会像这样:

Saved  Return
  a(4)    a(3)    a(2)    a(1)    a(0)    EBP   Address
------- ------- ------- ------- ------- ------- -------
5,0,0,0,4,0,0,0,3,0,0,0,2,0,0,0,1,0,0,0,x,x,x,x,y,y,y,y
^                                       ^
ESP                                     EBP

如果没有sub esp, 4,您将检索EBP的保留值,而不是您所说的当前返回地址。
在这部分之后,我给esp加上4,让它再次回到正确的位置。这是打印数组的正确方法吗?还是有另一种方法代替了在代码部分之前/之后加上4的sub/add esp?
这里没有错,但是你可以不用sub/add来解决这个问题

  • 如果已将-4的校正位移添加到加载EDX的指令:
mov edi, [input_length]
  print_array:
    mov edx, [esp + 4*edi - 4]
    ...
    dec edi
    jnz print_array
  • 或者如果您认为数组索引是从零开始的数量:
mov edi, [input_length]    ; eg. Array has 5 elements
    dec edi                    ; eg. Highest element has index 4
  print_array:
    mov edx, [esp + 4*edi]
    ...
    dec edi                    ; Lowest element has index 0
    jns print_array            ; Continue for all positive indexes

如果我想把数组保存在堆上,我该怎么做?
如果你需要去那条路,然后阅读有关它在Dynamic Heap Memory in x86 Assembly MASM
下面的代码版本在一个操作中为堆栈上的数组分配所需的空间,并按正常顺序存储数组元素(这更容易使用)。
第一个

相关问题