У вас есть пара вопросов. Во-первых, вы, похоже, не понимаете, что такое директива USES
для процедуры/функции. Если вы используете USES
и перечислите регистр (регистры), который сообщает ассемблеру сохранить значение этих регистров в стеке и восстановить их перед тем, как функция завершит работу. Это означает, что любое изменение, которое вы делаете в этом регистре в этой функции, не будет видно функции, которая его вызвала.
Руководство MASM говорит это о ИСПОЛЬЗУЕТ:
Синтаксис: ИСПОЛЬЗУЕТ reglist
Описание:
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 псевдо-опкод делает:
lengthof: Возвращает количество элементов в переменной массива.
Это может быть неясно, но этот псевдоокодирование - это количество элементов в массиве при сборке кода. Вы определяете массив оценок, как это:
scores DWORD MAXIMUMSCORES DUP(0)
В оценки массив всегда будет иметь значение lengthof из 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
Добавить оставшуюся часть источника. При минимальном значении _, код должен включать ваши функции 'ReadInt' и' WriteString'. Кроме того, вы должны запускать это в отладчике. Если это dos-based, используйте Turbo Debugger. Вы сразу увидите свою ошибку, если будете отлаживать код. ;) – enhzflep
@enhnzflep Я использую визуальную студию, чтобы написать ее, и отладчик для нее хорошо .. собака sh * t, на мой взгляд. О чем этот турбо-отладчик вы говорите? И что вы подразумеваете, добавив оставшуюся часть источника? – Bob
@enhzflep: Он использует библиотеку Irvine32. Некоторая полезная информация об этом есть [здесь] (http://math.uaa.alaska.edu/~afkjm/cs221/handouts/procedures.pdf) –