2017-01-09 80 views
-2

我必須用匯編語言做一個項目,我真的是堆棧。我想在生成一個隨機數(0-9)後,我選擇和編號,直到找到數字。 我不需要的東西這麼複雜,請彙編語言找到號碼

.MODEL SMALL 
.STACK 100H 
.DATA 

m1 DB 'The number is bigger ','$' 
m2 DB 'The number is smaller','$' 
m3 DB 'You won','$' 
m4 DB 'Choose the number ','$' 
.CODE 
MOV AX,@DATA 
MOV DS,AX 
MOV AH,09H 
MOV DX,OFFSET m4 
INT 21H 
RANDGEN:  
RANDSTART: 
    MOV AH, 00h 
    INT 1AH   

    MOV BH, 57 
    MOV AH, DL 
    CMP AH, BH  
    JA RANDSTART 

    MOV BH, 49 
    MOV AH, DL 
    CMP AH, BH 
    JB RANDSTART 


    mov ah, 2h 
    int 21h  
E1:MOV AH,01H 
INT 21H 
CMP AL,DL 
JG E2 
CMP AL,DL 
JL E3 
MOV AH,09H 
MOV DX,OFFSET m3 
INT 21H 
JMP E4 

E2:MOV AH,09H 
MOV DX,OFFSET m1 
JMP E1 

E3:MOV AH,09H 
MOV DX,OFFSET m2 
JMP E1 

E4:MOV AH,4CH 
INT 21H 
END 
+0

這是什麼架構?更詳細地解釋這是什麼以及你期望它做什麼。 – Rafael

+0

我想生成一個隨機數,然後選擇數字,直到我找到該數字。但是當我選擇一個數字時,我的程序總是顯示「您的數字更小」 –

回答

1

這是絕對必要的您將學習如何使用一些調試器,看你自己的代碼做什麼。

直到你找到一些調試,並學習如何在大會使用它,停止編程,有沒有點繼續,你只會浪費你的時間,甚至是別人,如果你把每一個瑣碎的問題堆棧溢出或其他一些論壇。

只有當你因爲不理解特定的東西而被「卡住」時,你才應該使用那些「互聯網」的東西。這意味着您可以很好地描述在某些短代碼之前CPU狀態是什麼,執行它之後是什麼,您期望什麼以及爲什麼/它與您的期望有什麼不同。然後人們可以向你解釋爲什麼你的期望是錯誤的。

但是,如果您還將使用指令參考指南來驗證您對特定指令的期望,那麼您將能夠在很短的時間內自行修復這些錯誤的90%。


有些事情你應該學會(重讀與新鮮的眼睛你的源應用這些發現代碼中的錯誤)。

  1. CPU寄存器是「超級全局變量」,誰寫了最後一個值到寄存器中,那個值就在它裏面。如果您想保留一段時間的值,請確保寄存器不會被下一部分代碼更改,或將值存儲在[堆棧]內存中的某處。或者將它複製(mov)到某個寄存器中,如果你需要那個值在此刻的那個,那麼這個寄存器不會被用在下一部分代碼中。

  2. DLDHDX都是CPU的相同寄存器,只是它的不同部分(位組)而已。 DX = DH * 256 + DL,或者當您將其視爲二進制數時,則DLDX的低8位,並且DH是高8位。 DX當然是8 + 8 = 16位。因此DH的第三位同時也是DX的第十一位,它在物理上是相同的。

  3. 標誌也只是一個數值在寄存器(F),它只受到一些指令的影響。如果你願意讀指令的參考指南,瞭解有關Jcc說明家庭(由條件碼跳),您將學習那些不影響F(標誌)的值,所以在這種情況下:

    CMP AL,DL 
    JG E2 
    CMP AL,DL 
    JL E3 
    

    這第二CMP會做什麼新的,第一個確實設置了標誌。在寄存器中的值是存在的,直到它被某些指令改變,它不會「蒸發」。通過在這樣一小段代碼中使用冗餘指令,你會顯示出缺乏理解或浪費的方法(冗餘指令會浪費CPU的週期,這在20世紀80年代是非常昂貴的事情,並且在這樣的小事情中會出現這種情況賺你很多的f眉和嘲弄...就像我在這裏所做的那樣(皺眉的部分是肯定的,不確定是否嘲弄,現在很難成爲混蛋,因爲人們在這個技能階段已經正常尋求建議,早在20世紀80年代,這就像要求公開羞恥一樣至少不能自己掌握基本知識,但現在它應該是OK))。

  4. 最後你的隨機數生成器:

    INT 1AH 
    
        MOV BH, 57 
        MOV AH, DL 
        CMP AH, BH  
        JA RANDSTART 
    
        MOV BH, 49 
        MOV AH, DL 
        CMP AH, BH 
        JB RANDSTART 
    

    這又浪費了大量的CPU週期,浪費了一些源代碼行,總體來說是不合理地神祕,所以源是不容易閱讀,並按照。考慮同樣的事情,這種替代方式:

    INT 1AH 
        ; cx:dx is 32 bit clock "time" in (1/18.21)s since boot 
        ; I will use the least significant 8 bits of it (DL) as random ASCII digit 
    
        CMP DL, '9' 
        JA RANDSTART 
        CMP DL, '0' ; your original code compares with '1'! 
        JB RANDSTART 
        ; so your original code will produce only 1-9 ASCII digits 
    

    這是同樣的事情(加固定到返回的0-9,而不是1-9位數)。請注意,現在來源「告訴」你的故事「與ASCII數字'9'比較,當以上時,做新的隨機數,然後與ASCII數字'0'比較,當下面,做新的隨機數。,任何經驗豐富的x86 ASM程序員都會閱讀,幾乎流利並立即明白。

  5. 以及關於那個「隨機」生成器的一件事。 DL是8位寄存器,所以它可以具有從0到2的值(當您將這8位顯示爲無符號整數時)。但是,只有當'0' <= DL <= '9',這是10個「合法」值DL纔會更進一步。如果時鐘返回ASCII字符':'58十進制),這將需要大約14秒鐘,直到DL將通過所有的58-255然後0-47值。這是一種非常慢的隨機生成器(也不是很隨機)。

    要通過簡單的方式有所改進,比如,你可以這樣做:

    INT 1AH 
        ; cx:dx is 32 bit clock "time" in (1/18.21)s since boot 
    
        AND DL,15  ; keep only bottom 4 bits (0-15) value in DL 
            ; (cheaply, AND is very fast bitwise operation) 
        CMP DL,9  ; it's 9 this time, not '9' (57). 
        JA RANDSTART ; values 10-15 will restart random 
         ; will keep restarting for 6/18.21 = ~0.33 of second 
         ; at most, puny human can wait that short while 
    
        ; remaining legal values 0-9 will be converted to ASCII digit 
        ADD DL,'0' 
        ; here DL is some "random" value from '0' to '9' 
        ; unfortunately the value '0' will be somewhat preferred over others 
    

如果你完全理解這些,並重新讀一遍你的源代碼,你應該能夠找到所有你的錯誤。或者更好的辦法是,使用調試器親眼看看每條指令的功能,以及每個指令在每個指令後發生的情況。

此外,如果你就會明白這些,你的下一個來源將是更具可讀性,更短,更易於破譯,既爲您和其他讀者。當您出示您當前的代碼,以一些有經驗的ASM程序員,他們會一直說「每個人都以某種方式學習它,它是一個開始OK」,但心靈的其他部分也會嚷嚷「殺吧,之前殺死它它會產卵。「通過做一些基本的重構,從你的源代碼中刪除基本的垃圾,如雙重/等,並使用適當的常量或Jcc別名下面的語義:你會做你的問題更容易閱讀和回答(加上答案將很可能的重點只是,省略了大量無用的bab)聲)。

由於您的代碼不使用任何內存存儲器,只需通過查看寄存器視圖和寄存器中的值(對於您在特定部分代碼中很重要),就可以非常容易地遵循CPU狀態的重要部分(在較大內存塊中跟蹤值比較乏味,但當然可行,如果出現這種需求,調試器也允許您查看內存內容)。

如果我沒有提到它,那麼學習使用一些調試器是絕對必要的。