簡體   English   中英

程序集:如何更改此代碼以要求用戶輸入

[英]Assembly: How to alter this code to ask for user input

我最近在 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();
}

我剛才需要幫助來更改我的代碼以允許用戶輸入,我有一種感覺,我可能需要做一個系統調用,但不確定是哪一個。 這幾乎是我第一天做組裝所以任何幫助將不勝感激

是的,您將需要使用系統調用。 在 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 那是因為 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選項編譯它,然后查看編譯器生成的程序集列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM