2017-12-15 16 views
-2

における数として出力して、良好な実装は次のようになりますのx86入力ベース2の数及びベース8

segment data use32 class=data 
    number dd 0 
    format_input db "%d", 0 
    format_output db "%x", 0 

segment code use32 class=code 
start: 
    push dword number 
    push dword format_input 
    call [scanf] 
    add esp, 4*2 

    push dword [number] 
    push dword format_output 
    call [printf] 
    add esp, 4*2 

実装はありベース2からベース8に番号を変換するために同様に?

+3

これは、変換の「実装」ではないCのライブラリ関数を呼び出すだけです。それがあなたには十分であれば、8進ではフォーマッタ '%o'があります。バイナリでは驚くべきことに私は何も見ないので、あなたの 'scanf'文書をチェックしなければなりません。それにもかかわらず、これは非常に基本的なものです。数値システムの背後にある数学を理解すれば、任意の基底を紙+ペン上の任意の基底に簡単に変換できるはずです。アセンブリにそのような数学を書くのは普通は簡単ではありません。特に2基の累乗が関係する場合は、ビット値を並べ替えるだけです。 – Ped7g

+0

I.基数2の入力は入力要素ごとに1つの重要なビットを持っています(ASCIIの場合は "010101"のようになります)、最も低いものを除いてすべてのビットを除外することができ、それはバイナリ入力です、ASCII '' 0 ''は '0011_0000' 「1」は「0011_0001」なので、このような文字列入力の最後のビットは0,1,0,1,0,1 ...となります)。8進数で出力するには1桁あたり3ビットが必要なので、それを '010'、 '101'にグループ化してそれらの2つの値、つまり「25」を出力するだけで十分です。 ...除算/乗算は必要ありません(ベース10のフォーマットとは異なり、何らかの乗除算が行われます)。 '0b010101 == 0o25' – Ped7g

+2

@ Ped7g:ISO C scanf/printf [基本2変換指定子がありません](https://stackoverflow.com/questions/11597863/why-does-scanfi-a-not-take-バイナリのような0b101)、それは標準的な拡張ではありません(glibcでさえも)(https://stackoverflow.com/a/112947/224132)。しかし、入力の場合、 'strtol'はargとして基数をとります。 –

答えて

1

これはessentially a duplicate of this C/C++ questionです。なぜなら、あなたはCライブラリ関数を呼び出すことによってそれを行う方法を尋ねているからです。それは大丈夫ですが、あなたはそれをasmで行うことはできません。私はちょうどコメントのためにちょっと長いことを正しく行う方法について十分に言えるので、重複として閉じないことにしました。

Cの構文は、どの機能を接着する必要があるのか​​を簡単に表現する方法ですので、基本的にCで答えていきます。asmのループを使って手順を実行したい場合は、バイナリ文字列を整数に変換するのはとても簡単です。一度に1つずつ数字をシフトするだけです。 (またはSSE2 pmovmskbを使用してください)。


printf %o出力をベース8で出力します。これはISO Cによって直接サポートされています。

Base 2 isn't, thoughしかし、strtoulは、文字列 - >符号なし整数をあなたが選択した基数で変換します。唯一残っている問題は、入力を文字列として読み込むことです。これを行う方法はたくさんありますが、基数2の数字に含まれない文字を過度に読み書きするのを避けたい場合は、0と1の文字のみを受け入れる%[]の変換でscanfを使用できます。

// optionally this buffer could be static like your `number`, but there's no reason to do that. 
char buf[65];  // reserve 65 bytes on the stack with sub esp, 80 (rounded up to keep stack 16B-aligned) 

buf[0] = 0;  // NULL terminate our stack buffer to avoid crashing in strtoul if scanf doesn't convert anything. 
int success = scanf(" %64[01]", buf); // skip optional whitespace and store up to 64 bytes + null terminator into buf 
// optional: check the conversion. 

unsigned long num = strtoul(buf, NULL, 2); // parse as base 2, returning a binary integer 

printf("%lo\n", num);   // print as octal 
// or %o if int and long are the same width in 32-bit asm 

これらのCステートメントのすべてのasm命令ではなく、ループのショートブロックで実装することができます。

だから、このようになりますASMを書くことができます。方法がわからない場合は、ask a compiler with gcc -O2 -S -masm=intel

scanfフォーマット文字列の長さ制限に注意してください。ユーザーがキーを押したままで、プログラムが1000バイトの1を読み取ると、バッファオーバーフローが発生しません。

現在、stdinバッファ内にある空白をスキップするために、フォーマット文字列の先頭の空白にも注意してください。 (例えば、scanfが通常消費しない前の行の最後の改行)。 Conversions like %c and %[ don't skip leading whitespace on their own

末尾の非数字文字を消費する場合は、%64sを使用します。 strtoulは、最初の非数字文字で停止します。 (そして、NULL以外の値をNULLに渡すとその位置へのポインタを格納します。

関連する問題