Сборка: проблемы с индексацией

У меня проблемы с выяснением, как сделать индексацию в моих циклах. я знаю esi используется для индексации, поэтому я пытаюсь использовать это...

    scores DWORD MAXIMUMSCORES DUP(0)
optionPromptMsg byte "Type 1 to continue or -1 to exit: ", 0
scorePromptMsg      byte "Enter your numeric score (0-100): ", 0
scoreErrorMsg       byte "Score out of range (0-100)!", 0
optionErrorMsg      byte "Only 0 or 1 allowed in option specification!", 0
resultMsg           byte " scores have been entered.", 0


.code
main proc
mov esi, 0
L1:
    mov edx, offset optionPromptMsg
    call WriteString
    call ReadInt
    mov ebx, 1
    cmp eax, ebx
    je L2
    mov ebx, -1               //99% sure my main is okay
    cmp eax, ebx
    je L3
    mov ebx, -2
    mov ecx, 2
    cmp ebx, eax
    ja L4
    cmp eax, ecx
    ja L4
    L2: call NextScore
    jmp L5
    L4: mov edx, offset optionErrorMsg
        call WriteString
        call Crlf
        jmp L5
    L5:
    loop L1
        L3 : call WriteScore



exit
main ENDP



WriteScore PROC USES esi //Thought was somehow make esi global?

mov eax, lengthof scores  //total number of items added to array
call writeInt
mov edx, offset resultMsg   
call WriteString
mov esi,0
L1:
    mov eax, scores[esi *4]
    call writeInt    //writes the numbers in the array
    inc esi
loop L1
mov eax, 5000
call Delay


ret
WriteScore ENDP

NextScore PROC USES esi

mov edx, offset scorePromptMsg
call WriteString
call ReadInt
mov ebx, 0
mov ecx, 100       
cmp ebx, eax
ja L1
cmp eax,ecx
ja L1
jmp L2
L1:
    mov edx, offset scoreErrorMsg
    call WriteString
    call Crlf
L2:
    mov scores[esi*4], eax //gets the next number and puts it in the array
    inc esi

ret
NextScore ENDP

Когда я запускаю его и добавляю 3 элемента в массив, он по какой-то причине говорит о длине scores равно 20, а затем, когда он распечатывает массив, числа даже не близки к тому, что я ожидаю, как правило, в миллионах или просто 0,

Любые предложения очень ценятся!

1 ответ

Решение

У вас есть пара вопросов. Во-первых, вы, кажется, не понимаете, что USES Директива о процедуре / функции предназначена для. Если вы используете USES и перечислить регистр (ы), который говорит ассемблеру сохранить значение этих регистров в стеке и восстановить их непосредственно перед выходом из функции. Это означает, что любые изменения, внесенные вами в этот регистр в этой функции, не будут видны функцией, вызвавшей ее.

В руководстве MASM говорится об ИСПОЛЬЗОВАНИИ:

Синтаксис: использует регистр

Описание:

 An optional keyword used with PROC. Generates code to push the
 value of registers that should be preserved (and that will be
 altered by your procedure) on the stack and pop them off when the
 procedure returns.

 The <reglist> parameter is a list of one or more registers. Separate
 multiple registers with spaces.

Поскольку вы, кажется, хотите, чтобы вызывающая функция видела изменения в ESI, сделанные в функции NextScore, вы захотите удалить оператор USES из этой процедуры. Изменить:

NextScore PROC USES esi

чтобы:

NextScore PROC

Теперь, когда вы увеличиваете ESI в следующем счете, оно не будет отменено при выходе из функции.

Другая проблема заключается в том, что длина псевдо-кода операции:

lengthof: возвращает количество элементов в переменной массива.

Это может быть не ясно, но этот псевдо-код операции - это число элементов в массиве, когда код был собран. Вы определяете массив баллов следующим образом:

scores DWORD MAXIMUMSCORES DUP(0)

Массив показателей всегда будет иметь значение длины MAXIMUMSCORES. Вместо того, чтобы использовать lengthof, вы должны просто использовать регистр ESI. Вы уже используете ESI для хранения количества элементов, добавленных в массив. Итак, этот код:

WriteScore PROC USES esi ; Thought was somehow make esi global?

    mov eax, lengthof scores  ; total number of items added to array
    call WriteInt

Может быть изменено на:

WriteScore PROC USES esi ; Thought was somehow make esi global?

    mov eax, esi  ; esi = number of items added to array
    call WriteInt

Другая проблема заключается в том, что вы не знаете, как loop инструкция работает. Из [x86 Инструкции] loop инструкция делает:

Выполняет операцию цикла, используя регистр ECX или CX в качестве счетчика. Каждый раз, когда выполняется инструкция LOOP, регистр счетчика уменьшается, а затем проверяется на 0. Если счетчик равен 0, цикл завершается, и выполнение программы продолжается с инструкцией, следующей за инструкцией LOOP. Если счетчик не равен нулю, выполняется близкий переход к операнду назначения (цели), который, вероятно, является инструкцией в начале цикла.

В вашем коде вы никогда не устанавливаете ECX на количество циклов, которое хотите зациклить, поэтому он будет использовать любое значение, которое будет в ECX. Вот почему у вас распечатано много дополнительных номеров. ECX должен быть инициализирован. Поскольку вы хотите просмотреть все введенные результаты, просто переместите ESI в ECX. Ваша функция WriteScore сделала:

    mov esi,0
L1:
    mov eax, scores[esi *4]
    call WriteInt    ; writes the numbers in the array
    inc esi
    loop L1

Мы можем изменить это так:

    mov ecx,esi      ; Initialize ECX loop counter to number of scores added
                     ; to the array.
    mov esi,0
L1:
    mov eax, scores[esi *4]
    call WriteInt    ; writes the numbers in the array
    inc esi
    loop L1

Теперь мы просто перебираем количество баллов (ESI), которое фактически ввел пользователь.

С учетом этих изменений ваша программа может выглядеть примерно так:

INCLUDE Irvine32.inc
INCLUDELIB Irvine32.lib
INCLUDELIB user32.lib
INCLUDELIB kernel32.lib

MAXIMUMSCORES equ 20

.data
scores DWORD MAXIMUMSCORES DUP(0)
optionPromptMsg byte "Type 1 to continue or -1 to exit: ", 0
scorePromptMsg      byte "Enter your numeric score (0-100): ", 0
scoreErrorMsg       byte "Score out of range (0-100)!", 0
optionErrorMsg      byte "Only 0 or 1 allowed in option specification!", 0
resultMsg           byte " scores have been entered.", 0

.code
main proc
    mov esi, 0
L1:
    mov edx, offset optionPromptMsg
    call WriteString
    call ReadInt
    mov ebx, 1
    cmp eax, ebx
    je L2
    mov ebx, -1               ; 99% sure my main is okay
    cmp eax, ebx
    je L3
    mov ebx, -2
    mov ecx, 2
    cmp ebx, eax
    ja L4
    cmp eax, ecx
    ja L4
L2: call NextScore
    jmp L5
L4: mov edx, offset optionErrorMsg
    call WriteString
    call Crlf
    jmp L5
L5:
    loop L1
L3: call WriteScore

    exit
main ENDP

WriteScore PROC USES esi ; We make changes to ESI not visible to caller
                         ; since we don't intend to change the number of scores
                         ; with this function. Any change to ESI in this function
                         ; will not appear to the caller of this function

    mov eax, esi      ; total number of items added to array in ESI
    call WriteInt
    mov edx, offset resultMsg
    call WriteString
    mov ecx,esi
    mov esi,0
L1:
    mov eax, scores[esi *4]
    call WriteInt    ; writes the numbers in the array
    inc esi
    loop L1
    mov eax, 5000
    call Delay
    ret
WriteScore ENDP

NextScore PROC ; We want changes to ESI to exist after we exit this function. ESI
               ; will effectively act as a global register.
    mov edx, offset scorePromptMsg
    call WriteString
    call ReadInt
    mov ebx, 0
    mov ecx, 100
    cmp ebx, eax
    ja L1
    cmp eax,ecx
    ja L1
    jmp L2
L1:
    mov edx, offset scoreErrorMsg
    call WriteString
    call Crlf
L2:
    mov scores[esi*4], eax ; gets the next number and puts it in the array
    inc esi

    ret
NextScore ENDP

END

Пример вывода этого:

Type 1 to continue or -1 to exit: 1
Enter your numeric score (0-100): 10
Type 1 to continue or -1 to exit: 1
Enter your numeric score (0-100): 20
Type 1 to continue or -1 to exit: 1
Enter your numeric score (0-100): 40
Type 1 to continue or -1 to exit: 1
Enter your numeric score (0-100): 650
Score out of range (0-100)!
Type 1 to continue or -1 to exit: 99
Only 0 or 1 allowed in option specification!
Type 1 to continue or -1 to exit: 1
Enter your numeric score (0-100): 100
Type 1 to continue or -1 to exit: -1
+5 scores have been entered.+10+20+40+650+100
Другие вопросы по тегам