我最近在 Windows 10 笔记本电脑上的 Visual Studio 2017 中编写了我的汇编程序。我现在希望更改此代码,将从用户获得的值放入注册表 eax、ebx、ecx 和 edx
\我已经让程序可以使用默认的硬编码值,但正在努力在网络上找到任何内容来帮助我获取用户输入。该任务指定我必须使用程序集来询问用户
.586 ;Enables assembly on non Priiliged intructions for the prntium processor
.model flat ,c ;model=Initialises the program memory mode, flat=Identifies the size of code and data pointers and
;c= identifies the naming and calling coventions
.stack 100h
.data ; This section will contain all of the static variables for our program
foo dd 0 ;Variable to be used to store into meory
.code ; Assembly code will be placed here
multi proc ; Start of the doit process. Like a method in C#. Method is called
;in the visual studio form Source
mov eax, 8 ; Moves the value 8 into the eax Registry
mov ebx, 4 ; Moves the value 4 into the ebx Registry
mov ecx, 6 ; Moves the value 6 into the ecx Registry
mov edx, 12 ; Moves the value 12 into the edx Registry
add eax, ebx ; Adds the value stored in registry ebx to the vale in eax and stores the answer in eax
add eax, edx ; Adds the value stored in registry edx to the vale in eax and stores the answer in eax
sub eax, ecx ; subtracts the value stored in registry ecx from the vale in eax and stores the answer in eax
mul ebx ; Multiply the value in registry eax with the value in eax and stores the answer in eax
mov [foo], eax ; stores the value in registry in eax into the computer memory
ret ; returns the valie of the accumulator
multi endp ; End of the doit method
end
这是我用来从 Visual Studio 调用它的代码
#include <iostream>
extern "C" int multi();
void main()
{
printf("%d%",multi());
std:getchar();
}
我现在需要帮助来更改我的代码以允许用户输入,我有一种感觉,我可能必须执行一个系统 cll,但不确定是哪一个。这实际上是我组装的第一天,因此我们将不胜感激
最佳答案
是的,您需要使用系统调用。在 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
函数非常简单。由于它不带任何参数,因此您无需担心传递任何内容。与 x86 上的所有函数一样,它在 EAX
寄存器中返回结果。
getchar
的返回值是用户输入的字符的 ASCII 代码。如果您想要一个数值,则需要从 ASCII 代码中减去 '0'
,利用数字 0 到 9 在 ASCII 表中是连续的这一事实。
但是,您需要将多次调用 getchar
的结果存储在某处,因为 x86 调用约定指定 EAX
、EDX
、ECX
寄存器容易被函数调用破坏(覆盖)。由于 ESI
、EBX
和 EDI
是调用保留的,因此我将它们用作临时寄存器。另一种选择是使用堆栈临时存储输入值。或者,优化代码以随时执行算术运算。
哦,请注意,虽然该函数的名称在 C 代码中为 getchar
,但当我们从汇编中调用它时,它的名称为 _getchar
。那是因为微软的编译器prepends an underscore to exported symbol names .
专家程序员会向此代码添加一些条件测试来检查错误。回想一下,失败时 getchar
返回 EOF
(-1)。您可能还想处理用户按下 Enter 键而不输入数字的情况。您可以使用相当于 while
循环 (cmp eax, -1
+ je
) 来继续旋转,直到 getchar
code> 返回一个您认为在范围内的值(例如,从 '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
option 编译它。 ,然后查看编译器生成的程序集列表。
关于windows - 汇编:如何更改此代码以请求用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54657639/