2017-09-26 114 views
0

我是x86-16位編程的新手。我非常難以正確地調用函數2來單獨從字符串中讀取字符。如果有人有任何想法,將不勝感激。下面的代碼顯示了我目前的嘗試(其中之一)。在MS-DOS /程序集中將單個字符從字符串打印到標準輸出中x86-16

.model small 
    .data 
     message db "Hello, DOS Here!", 0dh, 0ah 
    .code 
    main proc 
     mov ax, @data 
     mov ds, ax 
    L1: 
     mov ah, 2 
     mov bx, 1 
     int 21h 
     loop L1 

     .EXIT 
    main endp 
    end main 

我也應該使用push和pop來以相同的方法但是向後打印字符串。我確定我錯過了一些明顯的東西。我打印的時候得到的只是幾行的英鎊符號。 (Dec:156; Hex:9C)

+0

數你有機會獲得一個調試器?第一步是瞭解它爲什麼要輸出字符9C。調試器可以幫助解決這個問題。問問你自己是否每次都做同樣的事情,以及它從哪裏獲得「9C」。 –

+2

請參閱[Ralf Brown中斷列表](http://www.ctyme.com/intr/int-21.htm)。如果這看起來是一項家庭作業,那麼正確的做法是刷完筆記並最終在辦公時間訪問。 :)你的代碼顯示了缺乏x86彙編語言的基礎,我相信你不想在整個研究過程中拖動它。 –

+0

不知道你的意思是你的最新評論瑪格麗特,但我正在盡我所能進一步瞭解我的材料。這只是我掌握的許多資源之一。就像生活中的其他事情一樣,從各個角度得到建議總是很好的。你永遠不知道誰有一招或兩個袖子!感謝Moby的建議。我相信這將是處理這種語言的重要工具。它實際上是非常深入的(只要我已經閱讀了足夠的能夠理解它......在這一點上工作)。 – Rifleman192

回答

1

根據這個定義message db "Hello, DOS Here!", 0dh, 0ah,接下來的代碼將打印完整的消息:

mov ah, 02h 
mov dl, message  ;Get the H character 
int 21h 
mov dl, message+1 ;Get the e character 
int 21h 
mov dl, message+2 
int 21h 
mov dl, message+3 
int 21h 
mov dl, message+4 
int 21h 
mov dl, message+5 
int 21h 
mov dl, message+6 
int 21h 
mov dl, message+7 
int 21h 
mov dl, message+8 
int 21h 
mov dl, message+9 
int 21h 
mov dl, message+10 
int 21h 
mov dl, message+11 
int 21h 
mov dl, message+12 
int 21h 
mov dl, message+13 
int 21h 
mov dl, message+14 
int 21h 
mov dl, message+15 
int 21h 
mov dl, message+16 ;Get the 0Dh carriage return 
int 21h 
mov dl, message+17 ;Get the 0Ah linefeed 
int 21h 

而是愚蠢,止跌」你說?
爲了使用一個循環,並獲得很多緊湊的代碼,我們需要:

  1. 把你的郵件地址中的地址寄存器。您可以從SIDIBXBP中進行選擇。我在下面的代碼中選擇了BX
  2. 在此地址讀取一個字節。
  3. 用DOS輸出字節。
  4. 遞增地址寄存器中的指針。
  5. 通過檢查您剛剛輸出的換行符是否爲所有文本重複步驟2,3,4,5。因爲在你的文本中,這是最後一個字符。

一個版本的循環:

mov bx, OFFSET message ;1. 
Again: 
mov dl, [bx]   ;2. 
mov ah, 02h    ;3. 
int 21h 
inc bx     ;4. 
cmp dl, 0Ah    ;5. 
jne Again 

我也應該使用push和pop要能夠打印字符串中的相同方法,但倒退。

爲了實現你的這個下一個任務,你會放一個push dx在步驟2和3之間。然後寫一個額外的循環來顯示反轉的字符串:

Again2: 
pop dx 
mov ah, 02h 
int 21h 
cmp dl, "H" 
jne Again2 

的陷阱在這裏將這

  • 你不應該輸出之前,其他(實際)字符換行和回車==>提示:在開始第二循環
  • 前做2個 pop小號
  • 你不能輕易認爲「H」將只顯示爲文本的第一個字符==>提示:算push小號
+0

避免發佈完整的代碼解決方案作業問題。 –

1

警告:我幾十年沒有這樣做了,我沒有編譯器在我面前可以做到這一點。這看起來像一個任務,所以我不會寫代碼,但我會指出你在正確的方向。

Int 21h function 2要求您設置dl等於您要輸出的字符。這裏不需要推送和彈出,因爲DOS不使用棧來傳遞參數。首先,在循環之外,您希望將寄存器指向消息的地址,如:MOV si, message。然後,您需要從消息中取消引用單個字節並將其放入dl。這將需要使用間接地址表示法。然後你可以調用中斷21h並寫入字符。

至於循環,有幾種方法來處理它。您可以使用計數器,其中cx是典型的寄存器,並使用LOOP語句或DECJNZ語句。或者你可以在字符串的末尾放置一個標記,並在你點擊該標記時終止循環。空字符通常用於此目的。您還需要移動到字符串中的下一個字符。您可以通過添加一個索引或通過遞增循環中每次迭代的寄存器值來實現。就像INC si

說了這麼多,有一個更容易的方法,避免循環,但也許是作弊。看看interrupt 21h function 9

+0

是的,使用函數9會是'作弊',因爲它是其他練習之一(這很容易)。我已經修改了我的代碼,並從開始字符開始。我只需要弄清楚如何讓它移動到字符串中的下一個字符而不是ascii表中的下一個字符。以下是修訂: – Rifleman192

0

是的,使用函數9將是'作弊',因爲它是其他練習之一(這是一個簡單的練習)。我已經修改了我的代碼,並從開始字符開始。我只需要弄清楚如何讓它繼續循環,以便繼續讀取字符串而不是任意停止。這裏就是我這麼遠(它打印出H和15e中的):

 .model small 
    .data 
     message db "Hello, DOS Here!" 
    .code 
    main proc 
     mov ax, @data 
     mov ds, ax 

     mov ah, 2 
     mov cx, 16 
     mov dl, message 
    L1: 
     int 21h 
     mov dl, message + 1 
     loop L1 

     .EXIT 
    main endp 
    end main 
+1

瞭解間接尋址。 –

+0

此外,通過發佈此答案,您可能會得到低投票。我建議將它作爲您的問題編輯。 –

+0

感謝提示Moby。我是新來張貼在這裏,所以我會記住未來。 – Rifleman192

相關問題