使用随机值填充数组

时间:2015-07-23 21:19:06

标签: assembly parameter-passing masm irvine32

我在汇编语言课程中,我们正在进行练习,我们需要在堆栈上传递参数,以便在特定范围内生成 n 随机数。

我遇到的问题:
我的随机数不在我指定的范围内 2.当我返回此数组并尝试对其进行排序并再次显示时,该数组将填充不同的值。

我认为这些问题在某种程度上与我传递参数的方式有关。

TITLE Program 4         (Project04.asm)

INCLUDE Irvine32.inc

.data
intro_1 BYTE    "Composite Numbers          Programmed by ",0
prompt_1 BYTE   "This program generates random numbers in the range [100 .. 999],",0
prompt_2 BYTE   "displays the original list, sorts the list, and calculates the ",0
prompt_3 BYTE   "median value. Finally, it displays the list sorted in descending order.",0
prompt_4 BYTE   "How many numbers should be generated? [10 .. 200]: ",0
space3  BYTE    "   ",0
errorMessage BYTE   "Invalid input ",0
userNum DWORD   ?
min     =   10
max     =   200
lo      =   100
hi      =   999
array   DWORD   max DUP(?)

.code
main PROC
call    Introduction
push    OFFSET userNum
call    getData
;call   Randomize
push OFFSET array
push userNum
call fillArray1
push OFFSET array
push userNum
call displayList
call crlf
call crlf
push OFFSET array
push userNum
call sortList
push OFFSET array
push userNum 
call displayList
exit
main ENDP


    Introduction PROC
        mov edx, OFFSET intro_1
        call    WriteString
        call    crlf
        mov edx, OFFSET prompt_1
        call    WriteString
        call    crlf
        mov edx, OFFSET prompt_2
        call    WriteString
        call    crlf
        mov edx, OFFSET prompt_3
        call    WriteString
        call    crlf    
        call    crlf
        ret
    Introduction ENDP

;Get Data

    getData PROC

    getUserData:
        push ebp
        mov ebp, esp
        mov edx, OFFSET prompt_4
        call    WriteString
        call    ReadInt
        mov     userNum, eax
        ;call   crlf

    ;validate
        cmp eax, max
        ja  error1
        cmp eax, min
        jb  error1
        pop ebp
        ret
        error1:
            mov edx, OFFSET errorMessage
            call    WriteString
            call    crlf
            jmp getUserData

    getData ENDP

;Fill array

    fillArray1 PROC
        fillArray:
            push    ebp
            mov ebp,esp
            pushad          ; save registers
            mov esi,[ebp+12]    ; offset of array
            mov ecx,[ebp+8] ; array size
            cmp ecx,0       ; ECX == 0?
            je  L2          ; yes: skip over loop
            mov edx, hi 
            sub edx, lo

        L1:
            mov eax, edx
            call    RandomRange ; from the link library
            add eax, lo
            mov [esi], eax
            add esi, 4
            loop    L1

        L2: 
            popad           ; restore registers
            pop ebp
            ret 8           ; clean up the stack

    fillArray1 ENDP

;Sort List

    sortList PROC
        push    ebp
        mov ebp, esp
        mov ecx, [ebp + 8]
        dec ecx         ; decrement count by 1

        L1:
            push ecx            ; save outer loop count
            mov esi, [ebp + 12]     ; point to first value

        L2: 
            mov eax,[esi]       ; get array value
            cmp [esi+4],eax ; compare a pair of values
            jge L3          ; if [esi] <= [edi], don't exch
            xchg eax,[esi+4]    ; exchange the pair
            mov [esi],eax

        L3: 
            add esi,4       ; move both pointers forward
            loop L2     ; inner loop

            pop ecx     ; retrieve outer loop count
            loop L1     ; else repeat outer loop

        L4 :
            pop ebp
            ret 8  
    sortList ENDP

;Display Median

    displayMedian PROC
    displayMedian ENDP

我认为我的fillArray程序中的返回值可能已关闭?

displayList程序:

;Display list

    displayList PROC
        push    ebp
        mov ebp, esp
        mov ecx, [ebp + 8]
        jecxz   farewell
        mov esi, [ebp + 12]         ;set counter for the linebreak

    Print:
        mov eax, [ebx]
        call WriteDec
        dec esi
        jnz Spaces

    linebreak:
        call crlf
        mov esi, 10
        jmp Next

    Spaces:
        cmp esi, 0          ;if there has been ten elements, go to next line
        je  linebreak
        mov edx, OFFSET space3
        call WriteString

    Next:
        add ebx, 4
        loop Print


    pop ebp
    ret 8

    displayList ENDP

接受引用参数的getData过程:

;Get Data

    getData PROC
        push ebp
        mov ebp, esp
        pushad
        mov esi, [ebp + 8] ;move the address of the userNum

    getUserData:
        mov edx, OFFSET prompt_4
        call    WriteString
        call    ReadInt
        mov     userNum, eax
        mov     esi, userNum    ;move the userNum to the address
        ;call   crlf

    ;validate
        cmp eax, max
        ja  error1
        cmp eax, min
        jb  error1
        pop ebp
        ret
        error1:
            mov edx, OFFSET errorMessage
            call    WriteString
            call    crlf
            jmp getUserData

    getData ENDP

当我进行此更改时,在输入要打印的随机数后,程序崩溃。

1 个答案:

答案 0 :(得分:0)

fillArraysortList工作正常,我已对其进行了测试。

getDataerror1路径中有一个错误(确实很大),在打印错误消息后,您跳回getUserData再次创建堆栈帧。
将此创作移到getUserData标签上方,getData下方。

Introduction应该正常工作(未经过严格测试)。

main程序存在一些问题:

call    Introduction            ;OK

push    OFFSET userNum
call    getData                 ;getData takes no params
                                ;Either update getData (don't forget ret 04h)
                                ;or remove the push


;call   Randomize

push OFFSET array
push userNum
call fillArray1                 ;This should work

push OFFSET array
push userNum
call displayList                ;Don't know, no code for displayList

call crlf
call crlf
push OFFSET array
push userNum
call sortList                   ;This should work

;push OFFSET array              ;<-- This is commented
push userNum 
call displayList                ;!! You are not passing the array to display
                                ;That's why you will see different values

在重构其他功能后,您似乎忘记更新main

跟进

displayList程序似乎错了,因为:

  1. 您永远不会初始化ebx
  2. esi将保存数组指针,但您似乎将其用作计数器
  3. farewell未在任何地方定义
  4. 我认为这个新的displayList可能有用(请,请注意,我甚至没有编译它,我没有NASM,也没有计划安装

     ;Array
     ;Number of elements
     ;Elements per line   
     displayList PROC
            push    ebp
            mov ebp, esp
    
            push esi
            push ecx
            push edx
    
            mov esi, [ebp + 16]      ;Array
            mov ecx, [ebp + 12]      ;Items in array
    
        PrePrint:
            mov edx, [ebp + 8]       ;Counter for linebreaks
    
        Print:
            jecxz End
    
            lodsd
            call WriteDec            ;Print items
    
            mov edx, OFFSET space3
            call WriteString         ;Print space
    
            dec ecx
            dec edx
            jnz Print
    
            call crlf
        jmp PrePrint
    
        End:
            pop edx
            pop ecx
            pop esi
    
            pop ebp
            ret 12
    
        displayList ENDP
    

    注意这个新的displayList需要 3 个参数:

    push OFFSET array
    push userNum
    push 10              ;Items per line
    call displayList
    

    如果您想对每行的项目进行硬编码并删除过去的参数,请编辑该功能,请记得更新ret 12[ebp + xx]引用!

    在新的getData中,您忘记在popad之前执行pop ebp,并将ret替换为ret 04h