繁体   English   中英

Assembly MASM - 以正确的方式打印动态数组并将其保存在堆上

[英]Assembly MASM - Print dynamic array the correct way and saving it on the heap

我写了一个简单的程序,它需要一个数组长度,通过使用 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") 而不是打印的最后一个元素。 在这部分之后,我将 4 添加到 esp 以使其再次正确 position。 这是打印数组的正确方法还是在代码部分之前/之后有另一种方法而不是 sub/add esp by 4?

另外,如果我想将数组保存在堆上,我该怎么做? 我知道我需要声明一个变量,但是这个变量应该有动态长度,因为数组的长度是动态的,所以我不知道如何得到这个:/

正如您在“print_array”部分之前看到的那样,我需要将 esp 减 4,否则我会将当前返回地址打印为数组的第一个元素(因为它将是“esp+20”并且数组从“esp”开始+16") 而不是打印的最后一个元素。

您的偏移量告诉我您为数组输入了 5 个数字。 您的堆栈将如下所示:

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                                     Old EBP Return address

如果没有sub esp, 4您将检索到 EBP 的保留值,而不是您所说的当前返回地址。

在这部分之后,我将 4 添加到 esp 以使其再次正确 position。 这是打印数组的正确方法还是在代码部分之前/之后有另一种方法而不是 sub/add esp by 4?

这里没有错,但你可以在没有sub / add的情况下解决它

  • 如果您在加载 EDX 的指令中添加了 -4 的校正位移:

     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

另外,如果我想将数组保存在堆上,我该怎么做?

如果您需要 go 那样, 请在 x86 Assembly MASM 中的动态堆 Memory 中阅读它。


下面是一个代码版本,它在单个操作中为堆栈上的数组分配所需空间,并以正常顺序存储数组元素(更易于使用):

    push ebp
    mov  ebp, esp

; Prompt for the number of elements
    push offset str_insert_array_length
    call printf
    push offset input_length
    push offset str_input_format
    call scanf
    add  esp, 4 + 8             ; Combining both clean-ups

; Make room on the stack based on the number of elements
    mov  eax, [input_length]    ; eg. 5
    shl  eax, 2                 ; Is times 4 (size of integer)
    sub  esp, eax               ; eg. Minus 20

; Input the elements in the space between ESP and EBP
    mov  edi, esp
array_input:
    push offset str_insert_value
    call printf
    push edi                    ; No need to go via an extra variable!
    push offset str_input_format
    call scanf
    add  esp, 4 + 8

    add  edi, 4
    cmp  edi, ebp
    jb   array_input

; Print the elements from the space between ESP and EBP
    mov  edi, esp
print_array:
    mov  edx, [edi]
    push edx
    push offset str_format_print
    call printf
    add  esp, 8

    add  edi, 4
    cmp  edi, ebp
    jb   print_array

    pop ebp

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM