2016-10-08 5 views
0

私は、このアルゴリズムを使用して入力文字列内で最小の単語を検索するプログラムを作成しようとしています。TASMの文字列を変更

マイアルゴリズム:

Read character from input, but not echo 
If character is space: 
    current_string_length = 0; 
    current_string = ""; 
    echo character 
Else If character belong to English alphabet: 
    current_string_length++; 
    current_string += character; 
    if current_string_length < max_string_length: 
     max_string = current_string; 
     max_string_length = current_length_string; 
    echo character 
Else If character is "\n": 
    print max_string 

しかし、私は、アセンブリ内の新たなんだと文字列ときれいな文字列に文字を追加する方法を見つけることができません。どのように私はこれを行うことができますか、多分私はこのタスクのための別のアルゴリズムを選択する必要がありますか?

マイコード:

.model small 
.stack 100h        ; reserves 100h bytes for stack 

.data 
;---------------------------------------------------------------------------------- 
; Variables 
maxString   db 128 dup('$') 
currentString  db 128 dup('$') 
maxLength   dw 0 
currentLength  dw 0 
;---------------------------------------------------------------------------------- 
; Messages 
helloMessage db 10,13,'Assembly Shortest Word Finder Version 1.0 Copyright (c) 2016 RodionSoft',10,13,10,13,'Usage: enter string with length of words not more then 128 characters',10,13,10,13,10,13,10,13,'Enter string: $' 
resultMessage db 10,13,"Shortest word: $" 
;---------------------------------------------------------------------------------- 
; Program 
.code 
start : 
MOV AX, @data 
MOV DS, AX 
;---------------------------------------------------------------------------------- 
; Print helloMessage 
    lea dx, helloMessage    ; LEA - Load Affective Address 
    mov ah, 9       ; print the string of the adress 
    int 21h        ; present in DX register 


;---------------------------------------------------------------------------------- 
; main loop 
    repeat: 
     ; ------------------------------------------------------------------------- 
     ; Read character but not echo 
     mov ah, 08h      
     int 21h 
     mov ah, 0      ; ah = 0 

     cmp al, 13h      ; if(al == enter) 
     jz printResult     ; printResult() 
     cmp al, 20h      ; if(al == enter) 
     jz spaceinput     ; spaceInput() 
     ; ------------------------------------------------------------------------- 
     cmp al, 41h      ; if(al < 'A') 
     jl badInput      ; badInput() 
     cmp al, 7Ah      ; if(al > 'z') 
     jg badInput      ; badInput() 
     cmp al, 5Bh      ; if(al < '[') 
     jg goodInput     ; goodInput() 
     cmp al, 60h      ; if(al > '`') 
     jg goodInput     ; goodInput() 
     jmp badInput     ; else badInput() 

     goodInput: 
      inc currentString 
      ; currentString += al 


     badInput: 
      jmp repeat 

     spaceInput: 
      mov currentLength, 0 
      ;clean currentString 

     endOfIteration: 
      mov ah, 2      ; echo 
      int 21h 
      jmp repeat      ; loop 
;---------------------------------------------------------------------------------- 
printResult: 
    lea dx, secondMessage    
    mov ah, 9       
    int 21h 
    lea dx, maxString    
    mov ah, 9       
    int 21h 
;---------------------------------------------------------------------------------- 
exit: 
    MOV AX, 4c00h 
    INT 21h 

StringComparison proc 
    push cx dx bx ax bp si di   ; save general-purpose registers  

    mov cx, maxLength     ; cx = maxLength 
    mov dx, currentLength    ; dx = currentLength 
    cmp cx, dx       ; if(currentLength > maxLength) 
    jl currentBigger     ; currentBigger() 
    jmp return       ; else return 

    currentBigger: 
     ; maxString = currentString 
    return: 
    pop di si bp ax bx dx cx   ; restore general-purpose registers 
    ret 
endp 
end start 
+0

そのアルゴリズムはいろいろな点で私にはかなり間違っています...ループ本体とし、すべての値を初期化して、私がa、b、_、c、\ nを入力するとしましょう。アルゴリズムは、a、b、_、c、aを出力します。 (これはおそらく\ nを表示すると良いでしょうし、最短の文字列は "a"ではなく "c"です)...だから、まずこのタスクのアルゴリズムを修正し、いくつかの修正がどのように見えるかを考慮する必要があります。それを変更するのにはかなり近いですが、文字列の追加とクリアのためではありません。 – Ped7g

+0

アルゴリズムをCのように書くのではなく、1つの抽象度を上げてみてください。つまり、 "私は最短の単語を見つける" - > "found = none、単語の入力を解析し、 found = word " - > ....より簡単なステップに分割し、さまざまな入力で時々検証しても問題ありません。 ( "ab c \ n"と "a bc \ n"のような共通点だけでなく、 "\ n"や "\ n"のようなトリッキーなものも考慮してください) – Ped7g

+0

ありがとう、私はこのアルゴリズムをリファクタリングしようとします。文字列に文字を追加したり、アセンブリ言語で現在の単語を含む変数をクリーンアップするようにしますか? – Rodion

答えて

1

が文字列でクリーンな文字列に文字を追加する方法を見つけることができません。

まず最初に、文字列の定義に依存します(これはアセンブリの共通テーマです。データの保存方法を決定します。つまり、どのビット/バイトが何のために使用されますか?あげて)。

たとえば、resultMessageを参照してください。これはASCIIコード化された値を持つ連続したバイトで構成され、DOSサービスのターミネーターとして値'$'が使用されています。

C/C++では、古典的な文字列リテラルは似ていますが、ターミネータでは値0が使用されます。

パスカルの最初のバイトには文字列の長さが含まれ、長さに続いてASCII文字が含まれます。最後にはターミネータはありません。

Linuxでは、コンソールに文字列を表示するためのシステムコールは、DOS/C定義のように文字へのポインタをとりますが、ターミネータがなければ、文字列の長さは2番目の引数として用意する必要があります。彼はそれをどうやって得るのか。

文字列のような単純なもので、メモリに格納する方法はすでに4通りあります。

しかし、あなたの場合には、あなたはとてもおそらく最も簡単な方法は、いくつかのメモリバイト配列割り当てることです、最後の文字列でのみ動作する必要がありますが、それを構築し、それを変更しない:currentString db 128 dup('$')

をキープするためにend()ポインタをいくつかのレジスタに入れて、siとしましょう。

そして、一般的なタスクは次のように達成することができます(siに現在の終了()、およびcurrentStringとしてコンパイル時に固定されている文字列の先頭)だから、基本的に2つのポインタ

; all callable subroutines bellow expect the register "si" 
; to point beyond last character of currentString 
; (except the clearString of course, which works always) 

appendLetterInAL: 
    cmp  si,OFFSET currentString+127 ; 127 to have one byte for '$' 
    jae  appendLetterInAL_bufferIsFull_Ignore 
    mov  [si],al ; store new letter after previous last 
    inc  si  ; update "si" to point to new end() 
appendLetterInAL_bufferIsFull_Ignore: 
    ret 

clearString:   ; works also as INIT at the start of code 
    lea  si,[currentString] 
    ret 

prepareStringForDOSOutput: 
    mov  BYTE PTR [si],'$' ; set terminator at end() 
    lea  dx,[currentString] ; dx = pointer to string 
    ret 

getLengthOfString: ; sets cx to length of current string 
    ; lea  cx,[si - currentString] ; probably not allowed in 16b? 
    ; other variant 
    mov  cx,si 
    sub  cx,OFFSET currentString 
    ret 

copyCurrentStringToDI: 
    ; copies current string to buffer @di 
    ; and also terminates it in DOS way with '$' 
    ; upon return di contains original value 
    push bx 
    lea  bx,[currentString] 
    push di 
copyCurrentStringToDI_loop: 
    cmp  bx,si  ; all bytes copied 
    jae  copyCurrentStringToDI_finish 
    mov  al,[bx] 
    inc  bx 
    mov  [di],al 
    inc  di 
    jmp  copyCurrentStringToDI_loop 
copyCurrentStringToDI_finish: 
    mov  BYTE PTR [di],'$' ; set DOS terminator 
    pop  di     ; restore di to original value 
    pop  bx     ; restore also bx 
    ret 

は多くを行うのに十分ですそれを使った操作。

私はアルゴリズムと使用されたデータ構造がコードとコメントから理解しやすいことを願っています。

+0

使用例: 'call clearString'' call prepareStringForDOSOutput' 'mov ah、9'' int 21h'は空文字列を出力する必要があります) – Ped7g

+0

例2: 'call clearString'' mov al、 'x'' 'call appendLetterInAL'' call prepareStringForDOSOutput' 'mov ah、9'' int 21h'は "x"を出力します。 – Ped7g

+0

ありがとうございます。しかし、私は最短の文字列の長さを監視し、その値をcurrentStringの値に変更する必要がありますか?このコードを複製し、currentStringのsiとしていくつかのレジスタを使用する必要がありますか? – Rodion