程序集:如何更改此代码以请求用户输入



我最近在visual studio 2017中用windows 10笔记本电脑编写了我的汇编程序。我现在希望修改此代码,将从用户获得的值放入注册表eax、ebx、ecx和edx-

\我已经让这个程序处理了defalt硬编码的值,但我很难在网上找到任何东西来帮助我获得用户输入。任务指定我必须使用汇编来询问用户

.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     

这是我用来从visualstudio调用它的代码

#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函数非常简单。由于它不需要参数,所以您不需要担心传递任何东西。它在EAX寄存器中返回结果,就像x86上的所有函数一样。

getchar的返回值是用户输入的字符的ASCII代码。如果您想要一个数值,那么您需要从ASCII代码中减去'0',利用数字0到9在ASCII表中是连续的这一事实。

但是,您需要将结果存储在多次调用getchar的某个位置,因为x86调用约定指定EAXEDXECX寄存器会被函数调用破坏(覆盖)。由于ESIEBXEDI是保留调用的,所以我将它们用作临时寄存器。另一种选择是使用堆栈来临时存储输入值。或者,优化代码,以便在进行算术运算时进行运算。

哦,请注意,虽然函数的名称在C代码中是getchar,但当我们从汇编中调用它时,它是_getchar。这是因为微软的编译器在导出的符号名前面加了一个下划线。

专家程序员会在代码中添加一些条件测试来检查错误。回想一下,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++标准库,并且被迫使用操作系统调用,那么这将变得更加困难。我怀疑,这比你的教练在这个阶段所期望的要困难得多。您需要调用像ReadConsoleInput这样的Win32函数。不过,这里有一个技巧:编写函数C(或C++),使用/Fa选项进行编译,然后查看编译器生成的程序集列表。

相关内容

  • 没有找到相关文章

最新更新