2011-11-07 5 views
6

これは、純粋なアセンブリで行う必要があります(つまり、ライブラリやCの呼び出しは不要です)。アセンブリの整数をLinuxに出力する

私は問題の本質を理解しています。整数を10で除算し、1桁の剰余をASCIIに変換し、それを出力し、商を使ってプロセスを繰り返す必要があります。

何らかの理由で、機能していないだけです。私はx86上でNASMを使用しています。ここで

は、私が今まで持っているものだ(何も出力しませんが、いずれかの任意のアセンブラエラーをスローしません):

; integer to output is stored in eax 
mov ecx, 10 ; for base 10 

loop: 
div ecx ;EAX contains the quotient, EDX the remainder 

; Do something to EDX to convert it to ASCII, not sure if this is correct 
add edx, '0' 

push eax ;We'll be playing with EAX to output EDX, save EAX to the stack 

mov eax, 4    ; sys_write 
mov ebx, 1    ; to STDOUT 
mov ecx, edx 
mov edx, 1 
int 0x80 

pop eax ;restore EAX 

cmp eax, 0 ;If EAX is 0, our job is done 
jnz loop 

、これと同じ質問の数(すなわち、thisがあります。とthis)、私は実装が失われています。 This question(DOS用)も役に立ちましたが、私はまだ混乱しています。

私はここで何かを紛失しているはずです。思考?

+0

このコードのどこにでも定数10が表示されません。小数点を出力するために必要です。 (10桁で「div」と「mod」を繰り返し入力し、その桁を格納して反転して出力するか、「ビッグエンド」から最初に「100,000,000」、次に「10,000,000」で割ります。などがありますが、ストアアンドリバースの方法よりもそれほど複雑ではないかもしれません)。 – sarnold

+0

@sarnold一番上に行を挿入するのを忘れました。それを追加するために私の質問を編集しました。 –

+0

優秀!更新していただきありがとうございます。 – sarnold

答えて

3

さらに2つ以上の問題があります。言及@sarnold ecxの破損を超えて:

  1. div ecxecxによって64ビット値edx:eaxを分割するので、あなたは、分割前の0にedxを設定していることを確認する必要があります。

  2. writeシステムコールの第2引数(ecx)は、文字そのものではなく、印刷したい文字を含むバッファへのポインタでなければなりません。第二の問題を解決する1つの方法は、あなたがスタック上に印刷したい文字を含むレジスタをプッシュし、その後ecxにスタックポインタespを割り当てることです

(最近プッシュされた項目のスタックポインタのポイント、x86はリトルエンディアンの値を格納するため、最初のバイトは8ビットです)。例えばいくつかの出力を取得するのに十分であるべき

push edx   ; save value on stack 
mov eax, 4  ; sys_write 
mov ebx, 1  ; to STDOUT 
mov ecx, esp ; first byte on stack 
mov edx, 1  ; length = one byte 
int 0x80 
pop edx   ; remove what we pushed (or "add esp, 4" would do just as well here; 
       ;      we don't need the actual value again) 

...

(しかし、その時点で、あなたはあなたのアルゴリズムの「機能」を気づく、あなたが数字を保存する方法を再考したい場合があります

+0

これは大きな説明です。明確にしていただきありがとうございます。あなたは、このアルゴリズムが整数を逆に印刷する理由を理解しています。それを修正する上での任意の考えですか? –

+1

データセクション(例えば 'resb'ディレクティブを使用)やスタック(' esp'から減算するだけ)のいずれかで、数字のスペースを確保します(最大の符号なし32ビット整数は4294967295なので、10バイトで十分です)スタックを適切に整列させるために4の倍数を引いてください)。次に、転送先のバッファに数字を格納し、各文字を反転してバッファをループします。バッファの最後のバイトから始まり後方に向かってバッファに数字を格納すると、すべての数字を単一の 'write'システムコールで書くことができます。 –

2

あなたが適切にあなたのルーチンの先頭に10ecxを設定し、それ以降のecxを上書き:ループを通るたびに

mov eax, 4    ; sys_write 
mov ebx, 1    ; to STDOUT 
mov ecx, edx ;;; oops -- lost the 10 
mov edx, 1 
int 0x80 

loop 1アップラインを移動してみてください、そうecx10に再初期化されます。

+0

良いキャッチ、それを修正しました。私はまだ何も出力されていません、私の推測は 'add edxです、 '0'は1桁を10進数に正しく変換していません。 –

関連する問題