-1

私は現在、8086 のアセンブリでプログラミングしています。

私がやっている現在のタスクは、4 桁の 16 進数を 10 進数表現に変換することです。私は家庭教師の方法に従ってみましたが、特に0にするように言われたので、16進数に一時的な値を掛けなければならないセクションで混乱しています。 0になりますよね?

私がこれまでに持っているコードは以下の通りです。

; ------------------------------------
; Name    : Gethex
; Function: converts a word (4 hex digits) into a numerical value
; Inputs  : Upto a word hex values input into the console
; Outputs : Return within DX the numerical conversion
; ------------------------------------

Gethex:
MOV BX,0H ;Temp value to 0
MOV CX,0H ;Counter set to 0
Gethexloop:
call Getch
push DX ; Putch requires DL, need to save current reg
MOV DL,AL
call Putch
pop DX ; restore DL reg
MOV BH,AH ;Use BH as temp storage as AH will be corrupted
cmp AL,30H ; ASCII 0
JL Gethexloop ; If less than 0 jump to the start as not an Alphabetical char
cmp AL,39H ; ASCII 9
JLE Nums ; If less or equal to 9 then it will be a number
cmp AL,46H
JLE Case ; Start the conversion procedure
Case:
SUB AL,10
jmp Convert
Nums:
SUB AL,30 ; Convert to normal number
Convert:
push AX ; Prepare to multiply
MOV AX,BX
mul BX
POP AX
ADD AX,BX
ADD DX,AX ; final value
ADD CX,1 ; Increase counter
cmp CX,3 ; if greater than 4 (0 being included so 3)
JG EndLoop
jmp Gethexloop
EndLoop:
ret ; return to calling statement
4

1 に答える 1

1

いくつかの観察事項... まず、数字は数字です。「16 進数」と「10 進数」(および「2 進数」と「8 進数」) は、数値を表す方法であり、同じ数値です。「16 進数表現」を「10 進数表現」に 1 ステップで変換するのは難しいでしょう (ただし、可能です... と思います)。あなたがしたいことは、16 進数表現を数値に変換することです...そしておそらく数値を 10 進数表現に変換して、出力できるようにします。

「これまでの結果」と呼ぶのが好きな「一時」変数は、最初はゼロに設定されていますが、文字/数字ごとにゼロにリセットされません! 一般的な手順は、「これまでの結果」をゼロに設定し、検出された有効な数字ごとに、「これまでの結果」に基数を掛けることです。もちろん、文字から数字に変換されます。文字数がなくなるまで繰り返す

mulは完全に優れた命令ですが、「隠し」オペランド (この場合はaxand dx) があります。10 を掛ける場合、あまり選択肢はありませんが、16 を掛ける場合は、shl reg, 4「副作用」が少なくて済みます。本当に 8086 を使用している場合は、有効なオペランドは1とのみです。cl1 つ以外の「即時」は 80186 でのみ導入されました (実用的な目的のための 80286 - 80186 はまれでした)。ほぼ確実に使用できますが、おそらく「使用する必要はない」でしょう。これを使用するのが「想定」されているmulのではないかと思います-いずれにせよ、オーバーフローを簡単にチェックできます(そうしたい場合は、入力を4文字に制限することでオーバーフローを回避する必要があります)。

mov bh, ahあなたの行 の目的がわかりませんah。この時点で「興味深い」ものはありますか?

ほとんどのアセンブラは、 orcmp al, '0'と同じコードを受け入れます。前者の方が指示の目的がより明確になると思いますが、実際には問題ではありません。cmp al, 48cmp al, 30h

jlおよびjgは符号付きの数値用です -0FFhは -1 として解釈され、「0 未満」として比較されます。このコードでは、「負になるのに十分な大きさ」の数値に遭遇しないため、問題にはなりませんがjbja符号なしの数値 (0FFhは 255 と解釈されます) であり、「より正確」である可能性があります。それはほんの些細なことですが、違いを学ぶこともできます-時にはそれが重要な場合もあります.

    cmp AL,46H
    JLE Case ; Start the conversion procedure
Case:
    SUB AL,10

繰り返しますが、私はもっと好きcmp al, 'F'ですが、同じコードが生成されます。alが以下ではない場合(これjbeも符号なしの場合は正しいでしょう)、Case:とにかく失敗します。それがあなたの望むものかどうかは疑問です!そして、なぜあなたが 10 を引いているのかわかりません。私は 37 時間だと思っていたでしょう。とにかく '0' を引くなら 7 時間だと思いました。

厄介なユーザーは、'a'..'f' と 'A'..'F' を入力する可能性があります。適切な「タッパー」を行うには、キャラクターに「ケース」があることを確認する必要があります。ここでは、とにかく「A」..「F」以外を拒否するので、「大文字」を持たない文字を強制してジャンクを生成しても問題ありません。最初に 10 進数を破棄したことを確認してください。and al, 0DFh ; force to uppercase. あなたはそれをしたくないかもしれません - ユーザーにシフトキーを使わせるだけかもしれません。:)

ユーザー入力はキャリッジ リターン (13 または 0Dh) で終わります (思い出すと、Linux は改行 (10 または 0Ah) を使用しますが、dos は 13 だと思います)。10 進数または 16 進数の前に、最初に確認することをお勧めします。現在の設定では、ユーザーが「Enter」を押したとしても、ユーザーからの 4 文字を待機すると思います。おそらく期待した動作ではないでしょう...

はい、デバッガーを入手して、その使い方を学んでください。何が起こっているかを段階的に見ることは、あなたを大いに助けます。私はDavid LindauerのGRDBが好きでした...(DEBUGのように明るいだけです)...

于 2013-04-09T07:20:31.650 に答える