2016-08-22 202 views
0

我正在爲我的考試學習,而且我對這個彙編代碼感到困惑。這是一個程序,第一個用戶輸入一個字符串,而不是該字符串被編碼和打印,而不是解碼和打印。簡單編碼/解碼字符串混淆的彙編代碼?

令我困惑的是(德)編碼部分。因此,使用MyString的「LEA bx,MyString」內存地址保存在寄存器bx中。現在編碼發生。這樣做的目的是什麼?

INC bx 
MOV cl, [bx] 
XOR ch, ch 

coding: 
    INC bx 
    MOV dl, [bx] 
    XOR dl, ah 
    MOV [bx], dl 
LOOP coding 

爲什麼增加內存地址?這不是改變地址嗎?爲什麼要在循環中再次增加bx。這些指針只是混淆了我。我得到地址bx中的字符被移動到dl而不是用掩碼編碼的部分,而不是放回到dl。我對內存地址的增加感到困惑。這是否意味着它首先從第三個角色開始?比代碼字符串的3個字符與掩碼?前兩個比起來怎麼樣?對不起,如果問題很蠢,謝謝!

下面是完整的代碼:

.MODEL small 
.DATA 
    STR_LENGTH EQU 30 
    BUFF_LENGTH EQU STR_LENGTH + 3 
    MyString DB BUFF_LENGTH DUP (0) 
    Coder_Mask DB 128 
.STACK 
.CODE 

NewLine MACRO 
    MOV dl, 10 
    MOV ah, 02h 
    INT 21h 
    MOV dl, 13 
    MOV ah, 02h 
    INT 21h 
ENDM  

DeCode MACRO bx, ah 
LOCAL coding 

    INC bx 
    MOV cl, [bx] 
    XOR ch, ch 

    coding: 
     INC bx 
     MOV dl, [bx] 
     XOR dl, ah 
     MOV [bx], dl 
    LOOP coding 
ENDM 

WriteString MACRO bx 
LOCAL writing 

    INC bx 
    MOV cl, [bx] 
    XOR ch, ch 

    writing: 
     INC bx 
     MOV dl, [bx] 
     MOV ah, 02h 
     INT 21h 
    LOOP writing 
ENDM 

Start: 
    MOV ax, @DATA 
    MOV ds, ax 

    LEA bx, MyString 
    MOV cl, BUFF_LENGTH 
    MOV [bx], cl 
    LEA dx, MyString 
    MOV ah, 0Ah 
    INT 21h 

    NewLine 
    LEA bx, MyString 
    WriteString bx 

    LEA bx, MyString 
    MOV ah, Coder_Mask 
    DeCode bx, ah 

    NewLine 
    LEA bx, MyString 
    WriteString bx 

    NewLine 

    LEA bx, MyString 
    MOV ah, Coder_Mask 
    DeCode bx, ah 

    NewLine 
    LEA bx, MyString 
    WriteString bx 

    MOV ax, 4C00h 
    INT 21h 
END Start 

回答

3

您需要了解內存的結構以及字符串的存儲方式。

老師的代碼缺少任何意見,所以這是您的任務(或者您失敗了),或者由於外交原因,我不會評論您的老師。

串緩衝器的結構爲的int 21h功能0Ah使用MS-DOS的一個(description):

MyString: 
    db string_maximum_size  ; maximum characters to store into buffer 
    db character_actually_read ; characters read by INT 21h: 0Ah function 
    db string_maximum_size DUP (0) ; the string characters 

所以通過輸入字符串「hello」在地址MyString存儲器將被設置爲:
33, 5, 104 ('h'), 101 ('e'), 108 ('l'), 108 ('l'), 111 ('o')然後是26個零(結果爲DUP (0))。

其實我認爲你的代碼有bug,設置最大尺寸爲總緩衝區大小BUFF_LENGTH EQU STR_LENGTH + 3,而來自中斷描述我期望第一個字節只包含STR_LENGTH。您可以通過嘗試輸入長度爲33個字符的字符串來驗證這一點,並在調試器中檢查內存是否在MyString緩衝區之後被覆蓋。此外,+3沒有多大意義,因爲只有+2字節用於最大大小和實際大小。

現在,在代碼發生這樣的:

LEA bx,[MyString] ; bx = address of first byte of buffer (contains maximum size) 
INC bx    ; bx now points to actual size 
; instead LEA bx,[MyString+1] could have been used, skipping one INC bx 
MOV cl,[bx]   ; cl = actual string size 
XOR ch,ch   ; ch = 0 (extending 8 bit value in cl to unsigned 16 bit in cx) 
; other option on 386+ CPU is MOVZX cx,BYTE PTR [bx] 
; or XOR cx,cx MOV cl,[bx] 
INC bx    ; bx now points to the first character 

它使然後用[bx]內容不管它願意的話,循環期間再次增加bx訪問下一個字符,直到cx計數器也達到0做。


你一定要啓動調試,一步槽,通過指令點存儲器窗口MyString代碼指令,並且,看如何bx用於有訪問特定字節,這些INC bx如何適應這一點。

這將解釋它甚至比其他任何事情都更好。


編輯:

一兩件事。我其實保留了一個祕密,這是你問題的組成部分。

所以「我怎麼知道?」:你應該總是記得,計算機是計算機器。你在(指令列表)中加入了一些程序,你輸入了一些數字,讓它執行指令,然後得到結果數字。

我有代碼(說明)。接下來我在代碼中尋找的是「如何定義字符串」。我發現它是由用戶輸入的,通過int 21h功能讀取。所以我搜索了這個函數,它是如何工作的,它返回了什麼數據。 管理單元:突然之間,所有的東西都變得有意義了(除了最大長度的錯誤,我認爲這只是一個來自你的lector的錯誤,即使是經驗豐富的程序員也很容易在ASM中做一些錯誤)。

所以始終確保你瞭解所有的指令和你瞭解清楚什麼是輸入數據(它們的結構和值)。然後,您可以像在CPU上一樣在腦海中運行所有內容,以瞭解這些輸入數據如何轉化爲輸出數據。這是一個純粹的確定性的計算過程,你需要猜測什麼,這正是定義在計算中的每一個階段接下來會發生什麼。

如果你確切地知道那些是什麼定義,它實際上是直截了當容易,比任何高層次的抽象的東西更容易,只是更多的繁瑣。

如果你是新的ASM,它更容易觀看這種情況發生在調試器(它也將幫助您瞭解ASM更快),比你的頭做。

+0

順便說一句,像這樣存儲字符串是很不尋常的,這很明顯,爲什麼在這種情況下使用這個結構(因爲字符串的輸入是通過'int 21h'的0A函數完成的),但這不是一般的藍圖,在ASM中實現字符串。實際上C/C++使用零終止的字符串(沒有任何長度的字節),並且一些DOS的int 21h函數用於打印字符串,使用''''終止的字符串(不含長度),而BIOS中斷函數通常需要字符串的長度作爲參數。 – Ped7g

+0

非常感謝。 – Shallan

+0

@Shallan我加了「如何」推理。嘗試與你的其他例子考試,它應該有所幫助。 :) – Ped7g

0

解釋:

INC bx ; increment bx, skip this byte (why ?) 
MOV cl, [bx] ; get number of characters of the string 
XOR ch, ch ; quick way to set ch to zero, so cx == cl for the loop 

coding: 
    INC bx ; next address 
    MOV dl, [bx] ; get character value 
    XOR dl, ah ; decode it with XOR key in ah 
    MOV [bx], dl ; store in the same memory value 
LOOP coding  ; decrement cl and goto coding if cx > 0 

格式字符串似乎「自定義」,當然不是NULL終止,而是包含尺寸第一(是帕斯卡艾達?使用這種系統)

  • 第一個字節似乎忽略那裏。
  • 第二個字節包含以下字符串
  • 長度的數據的其餘部分是字符串本身

。注意,在這種情況下,編碼和解碼是相同的,因爲使用XOR掩蔽。

+0

爲什麼 「MOV CL,[BX]」 得到字符數和 「MOV DL,[BX]」 得內存值?這是我們教授寫給我們的代碼,所以我不明白其中的一半。我猜他正在使用編碼方法,而不是編碼其他字符。並且他在ch中存儲0,所以cx(對於LOOP,因爲它遞減cx)等於字符數可能是? – Shallan

+0

檢查格式。首先獲取1個字節的字符串大小,然後遍歷字符串數據並在字符上應用XOR。所有字符都被編碼,只是字符串格式有2個前導字節,1個未知和1個大小。 'WriteString'宏是這個證明,因爲它能夠正確地打印字符串並使用相同的循環。並且ch被設置爲零,因爲循環在cx上完成,並且只有cl被設置。 –

+0

爲什麼沒有「MOV cl,[bx]」將字節從bx的地址移動到cl ..是否因爲它是coutner寄存器?當它是與dl寄存器相同的命令時,它將移動該字節,因爲它是數據寄存器? – Shallan