Да, вам нужно будет использовать системный вызов.В C ++ вы бы вызывали std::getchar()
, чтобы прочитать символ из стандартного ввода.Если вам разрешено использовать стандартную библиотеку C ++, если вы вызываете ее из сборки, тогда код будет выглядеть примерно так:
multi proc
push esi ; \ preserve
push ebx ; | callee-preserve
push edi ; / registers
call _getchar ; read input; return result in EAX
mov esi, eax ; ESI = EAX
sub esi, 48 ; ESI -= '0'
call _getchar ; read input; return result in EAX
mov ebx, eax ; EBX = EAX
sub ebx, 48 ; EBX -= '0'
call _getchar ; read input; return result in EAX
mov edi, eax ; EDI = EAX
sub edi, 48 ; EDI -= '0'
call _getchar ; read input; return result in EAX
mov edx, eax ; EDX = EAX
sub edx, 48 ; EDX -= '0'
mov ecx, edi ; ECX = EDI
mov eax, esi ; EAX = ESI
add eax, ebx ; EAX += EBX
add eax, edx ; EAX += EDX
sub eax, ecx ; EAX -= ECX
mul ebx ; EDX:EAX = EAX * EBX
mov [foo], eax ; *foo = EAX
pop edi ; \ restore
pop ebx ; | callee-preserve
pop esi ; / registers
ret
multi endp
Вызов функции getchar
очень прост.Поскольку он не требует параметров, вам не нужно беспокоиться о передаче чего-либо.Он возвращает свой результат в регистр EAX
, как и все функции в x86.
Возвращаемое значение getchar
- это код ASCII для введенного пользователем символа.Если вам нужно числовое значение, вам нужно вычесть '0'
из кода ASCII, используя тот факт, что числа от 0 до 9 являются последовательными в таблице ASCII.
Однако вам нужно сохранить результатгде-то в нескольких вызовах getchar
, так как соглашение о вызовах x86 указывает, что регистры EAX
, EDX
и ECX
могут быть перекрыты (перезаписаны) вызовом функции.Поскольку ESI
, EBX
и EDI
сохраняются при вызове, я использовал их в качестве временных регистров.Другой альтернативой будет использование стека для временного хранения входных значений.Или, оптимизируя код для выполнения арифметических операций по ходу дела.
О, и обратите внимание, что хотя имя функции в коде C и равно getchar
, когда мы вызываем ее из сборки, это _getchar
.Это связано с тем, что компилятор Microsoft добавляет подчеркивание к экспортированным именам символов .
Опытный программист добавил бы в этот код некоторые условные тесты, которые проверяют наличие ошибок.Напомним, что getchar
возвращает EOF
(-1) при ошибке.Возможно, вы также захотите обработать случай, когда пользователь нажимает клавишу Enter без ввода номера.Вы можете использовать эквивалент цикла while
(cmp eax, -1
+ je
), чтобы вращаться до тех пор, пока getchar
не вернет значение, которое, по вашему мнению, находится в пределах диапазона (от '0'
до '9'
, скажем,).
Обратите внимание (предупреждение: полностью не проверено!):
ReadInteger proc
TryAgain:
call _getchar ; read input from stdin; return result in EAX
cmp eax, 48 ; \ if (input < '0')
jl TryAgain ; / jump to TryAgain
cmp eax, 57 ; \ if (input > '9')
jg TryAgain ; / jump to TryAgain
sub eax, 48 ; input -= '0'
ret
ReadInteger endp
multi proc
push esi
push ebx
push edi
call ReadInteger
mov esi, eax
call ReadInteger
mov ebx, eax
call ReadInteger
mov edi, eax
call ReadInteger
add eax, esi
add eax, ebx
sub eax, edi
mul ebx
mov [foo], eax
pop edi
pop ebx
pop esi
ret
multi endp
Если вы не можете использовать стандартную библиотеку C ++ и вынуждены использовать вызовы операционной системы, тогда это становится намного болеесложно.Я подозреваю, что это гораздо сложнее, чем твой инструктор мог бы ожидать от тебя на этом этапе.Вам нужно вызвать функцию Win32, например ReadConsoleInput
.Здесь есть хитрость: напишите функцию C (или C ++), скомпилируйте ее с опцией /Fa
и посмотрите список сборок, созданный компилятором.