5

NASMアセンブリを学ぼうとしていますが、高水準言語のように見えるものに苦労しているようです。

私が使用しているすべての教科書は、文字列の使用について説明しています。実際、それは彼らのお気に入りの1つであるようです。hello worldの印刷、大文字から小文字への変更など。

ただし、NASMアセンブリで16進数をインクリメントおよび印刷する方法を理解しようとしていますが、続行する方法がわかりません。たとえば、16進数で#1-nを出力したい場合、Cライブラリ(私が使用できるすべての参照)を使用せずにどのように印刷しますか?

私の主なアイデアは、.dataセクションに変数を設定し、それをインクリメントし続けることです。しかし、この場所から16進値を抽出するにはどうすればよいですか?最初に文字列に変換する必要があるようです...?

アドバイスやサンプルコードをいただければ幸いです。

4

4 に答える 4

9

最初に、入力としてニブル値(0..15)を取り、16進文字( '0' .. '9'、'A' ..'F')を出力する単純なルーチンを記述します。

次に、バイト値を入力として受け取るルーチンを作成し、上記のルーチンを2回呼び出して、2つの16進文字を出力します。つまり、ニブルごとに1つです。

最後に、Nバイト整数の場合、この2番目のルーチンをN回(バイトごとに1回)呼び出すルーチンが必要です。

これを最初に擬似コードまたはCなどのHLLで表現してから、これをasmに変換する方法を考えると役立つ場合があります。

void print_nybble(uint8_t n)
{
    if (n < 10) // handle '0' .. '9'
        putchar(n + '0');
    else // handle 'A'..'F'
        putchar(n - 10 + 'A');
}

void print_byte(uint8_t n)
{
    print_nybble(n >> 4); // print hi nybble
    print_nybble(n & 15); // print lo nybble
}

print_int16(uint16_t n)
{
    print_byte(n >> 8); // print hi byte
    print_byte(n & 255); // print lo byte
}
于 2010-10-04T08:53:36.513 に答える
1

これは宿題ですか?

ビットはビットです。ビット、バイト、ワード、ダブルワード、これらはハードウェア用語であり、命令セット/アセンブラが参照するものです。16進数、10進数、8進数、符号なし、符号付き、文字列、文字などは、プログラミング言語の表現です。同様に、.text、.bss、.dataなどもソフトウェアツールの表現であり、命令セットは1つのアドレスが.dataであり、もう1つが.textであることを気にせず、どちらの方法でも同じ命令です。これらのプログラミング言語がすべて存在する理由はいくつかありますが、非常に正当な理由がある場合もありますが、この問題を解決しようとするときに混乱しないでください。

ビットから人間が読める形式のASCIIに変換するには、最初にASCIIテーブル、ビット単位の演算子、または論理シフト、算術シフトなどを知る必要があります。さらに、ロードとストアなどが必要です。

レジスタ/メモリ内のある数値からASCII16進数に変換するために必要なことを数学的に考えてください。0b0001001000110100である0x1234と言います。人間がそれを読むためには、はい、より良い用語がないために文字列に入れる必要がありますが、何かをするために隣接するメモリ位置に4文字とnullを格納する必要はありません。出力関数によって異なります。通常、文字ベースの出力エンティティは、何度も呼び出されるある種の単一のoutput_char()に要約されます。

文字列に変換することもできますが、それはより手間がかかります。計算するASCII文字ごとに、ある種の単一文字ベースの出力関数をすぐに呼び出します。putchar()は、バイト出力文字タイプ関数の例です。

したがって、バイナリの場合、一度に1ビットを調べて、0x30または0x31を作成する必要があります。8進数の場合、一度に3ビットで、0x30から0x37を作成します。16進数は、一度に4ビットに基づいています。

16進数には、使用する16文字がASCIIテーブルで互いに隣接して見つからないという問題があります。したがって、0〜9の場合は0x30〜0x39を使用しますが、好みや要件に応じて、A〜Fの場合は0x41〜0x46または0x61〜0x66を使用します。したがって、各ニブルについて、0xFとANDで比較し、9と比較して0x30または0x37を追加します(10 + 0x37 = 0x41、11 + 0x37 = 0x42など)。

レジスタ内のビットからバイナリのASCII表現への変換。メモリ内のビットが1である場合、ビットの1(0x31 ascii)は0であり、0(asciiでは0x30)を示します。

void showbin(unsigned char x)
{{
    unsigned char ra;

    for(ra = 0x80; ra; ra >> = 1)
    {{
        if(ra&x)output_char(0x31); else output_char(0x30);
    }
}

上記のunsignedcharを使用するのは理にかなっているように思われるかもしれませんが、unsigned intは、ターゲットプロセッサによっては、はるかに優れた(よりクリーンで高速な)コードを生成できます。しかし、それは別のトピックです

上記は、アセンブラでは次のようになります(意図的にx86を使用していません)

..。
 mov r4、r0
 mov r5、#0x80
上:
 tst r4、r5
 moveq r0、#0x30
 movne r0、#0x31
 bl output_char
 mov r5、r5、lsr#1
 cmp r5、#0
 bneトップ
 ..。

展開すると書き込みが簡単になり、少し速くなります。トレードオフは、より多くのメモリを使用することです。

..。
 tst r4、#0x80
 moveq r0、#0x30
 movne r0、#0x31
 bl output_char
 tst r4、#0x40
 moveq r0、#0x30
 movne r0、#0x31
 bl output_char
 tst r4、#0x20
 moveq r0、#0x30
 movne r0、#0x31
 bl output_char
 ..。

9ビットの数値があり、8進数に変換したいとします。一度に3ビットを取り(人間は左から右に読むので、上のビットから始めます)、0x30を追加して0x30から0x37を取得します。

..。
mov r4、r0
mov r0、r4、lsr#6
およびr0、r0、#0x7
r0、r0、#0x30を追加します
bl output_char
mov r0、r4、lsr#3
およびr0、r0、#0x7
r0、r0、#0x30を追加します
bl output_char
およびr0、r4、#0x7
r0、r0、#0x30を追加します
bl output_char
..。

16進数の1バイト(8ビット)は次のようになります。

..。
mov r4、r0
mov r0、r4、lsr#4
およびr0、r0、#0xF
cmp r0、#9
addhi r0、r0、#0x37
addls r0、r0、#0x30
bl output_character
およびr0、r4、#0xF
cmp r0、#9
addhi r0、r0、#0x37
addls r0、r0、#0x30
bl output_character
..。

1からNまでのループを作成し、その値をメモリに格納してメモリ(.data)から読み取り、16進数で出力します。

..。
mov r4、#1
str r4、my_variable
..。
上:
ldr r4、my_variable
mov r0、r4、lsr#4
およびr0、r0、#0xF
cmp r0、#9
addhi r0、r0、#0x37
addls r0、r0、#0x30
bl output_character
およびr0、r4、#0xF
cmp r0、#9
addhi r0、r0、#0x37
addls r0、r0、#0x30
bl output_character
..。
ldr r4、my_variable
r4、r4、#1を追加します
str r4、my_variable
cmp r4、#7;たとえばNは7です
bneトップ
..。
my_variable .word 0

十分なレジスタがある場合、RAMに保存するのは少し無駄です。x86を使用すると、メモリを直接操作でき、レジスタを経由する必要はありません。

x86は、上記の(ARM)アセンブラーと同じではないため、同等の機能を理解するための演習として残されています。重要なのは、それはシフトとアンディングであり、その問題を追加して、それを基本的なステップに分解し、そこから指示が自然に落ちるということです。

于 2010-10-05T06:54:38.043 に答える
1

速くて汚いGASマクロ

.altmacro

/*
Convert a byte to hex ASCII value.
c: r/m8 byte to be converted
Output: two ASCII characters, is stored in `al:bl`
*/
.macro HEX c
    mov \c, %al
    mov \c, %bl
    shr $4, %al
    HEX_NIBBLE al
    and $0x0F, %bl
    HEX_NIBBLE bl
.endm

/*
Convert the low nibble of a r8 reg to ASCII of 8-bit in-place.
reg: r8 to be converted
Output: stored in reg itself.
*/
.macro HEX_NIBBLE reg
    LOCAL letter, end
    cmp $10, %\reg
    jae letter
    /* 0x30 == '0' */
    add $0x30, %\reg
    jmp end
letter:
    /* 0x57 == 'A' - 10 */
    add $0x57, %\reg
end:
.endm

使用法:

mov $1A, %al
HEX <%al>

<>次の理由で使用され.altmacroます:デフォルトパラメータにパーセント記号が含まれるガスaltmacroマクロは、「%演算子には絶対式が必要」で失敗します

結果:

  • %al'1'ASCII形式の0x31が含まれています
  • %bl'A'ASCII形式の0x41が含まれています

今、あなたはあなたがやりたいことを何でもすることができます%al%bl例えば:

  • 複数のバイトをループしてメモリにコピーします(バイトの2倍のメモリを割り当てるようにしてください)
  • システムまたはBIOS呼び出しでそれらを印刷します
于 2015-09-24T08:02:41.120 に答える
-1

Intel構文。これは私のブートローダーからのものですが、あなたはアイデアを得ることができるはずです。

print_value_of_CX:

    print_value_of_C_high:

        print_value_of_C_high_high_part:
            MOV AH, CH
            SHR AH, 0x4
            CALL byte_hex_printer

        print_value_of_C_high_low_part:
            MOV AH, CH
            SHL AH, 0x4
            SHR AH, 0x4
            CALL byte_hex_printer

    print_value_of_C_low:

        print_value_of_C_low_high_part:
            MOV AH, CL
            SHR AH, 0x4
            CALL byte_hex_printer

        print_value_of_C_low_low_part:
            MOV AH, CL
            SHL AH, 0x4
            SHR AH, 0x4
            CALL byte_hex_printer

byte_hex_printer:
    CMP AH, 0x00
    JE move_char_for_zero_into_AL_to_print
    CMP AH, 0x01
    JE move_char_for_one_into_AL_to_print
    CMP AH, 0x02
    JE move_char_for_two_into_AL_to_print
    CMP AH, 0x03
    JE move_char_for_three_into_AL_to_print
    CMP AH, 0x04
    JE move_char_for_four_into_AL_to_print
    CMP AH, 0x05
    JE move_char_for_five_into_AL_to_print
    CMP AH, 0x06
    JE move_char_for_six_into_AL_to_print
    CMP AH, 0x07
    JE move_char_for_seven_into_AL_to_print
    CMP AH, 0x08
    JE move_char_for_eight_into_AL_to_print
    CMP AH, 0x09
    JE move_char_for_nine_into_AL_to_print
    CMP AH, 0x0A
    JE move_char_for_A_into_AL_to_print
    CMP AH, 0x0B
    JE move_char_for_B_into_AL_to_print
    CMP AH, 0x0C
    JE move_char_for_C_into_AL_to_print
    CMP AH, 0x0D
    JE move_char_for_D_into_AL_to_print
    CMP AH, 0x0E
    JE move_char_for_E_into_AL_to_print
    CMP AH, 0x0F
    JE move_char_for_F_into_AL_to_print

        move_char_for_zero_into_AL_to_print:
        MOV AL, 0x30
        CALL print_teletype_stringB
        RET
        move_char_for_one_into_AL_to_print:
        MOV AL, 0x31
        CALL print_teletype_stringB
        RET
        move_char_for_two_into_AL_to_print:
        MOV AL, 0x32
        CALL print_teletype_stringB
        RET
        move_char_for_three_into_AL_to_print:
        MOV AL, 0x33
        CALL print_teletype_stringB
        RET
        move_char_for_four_into_AL_to_print:
        MOV AL, 0x34
        CALL print_teletype_stringB
        RET
        move_char_for_five_into_AL_to_print:
        MOV AL, 0x35
        CALL print_teletype_stringB
        RET
        move_char_for_six_into_AL_to_print:
        MOV AL, 0x36
        CALL print_teletype_stringB
        RET
        move_char_for_seven_into_AL_to_print:
        MOV AL, 0x37
        CALL print_teletype_stringB
        RET
        move_char_for_eight_into_AL_to_print:
        MOV AL, 0x38
        CALL print_teletype_stringB
        RET
        move_char_for_nine_into_AL_to_print:
        MOV AL, 0x39
        CALL print_teletype_stringB
        RET
        move_char_for_A_into_AL_to_print:
        MOV AL, 0x41
        CALL print_teletype_stringB
        RET
        move_char_for_B_into_AL_to_print:
        MOV AL, 0x42
        CALL print_teletype_stringB
        RET
        move_char_for_C_into_AL_to_print:
        MOV AL, 0x43
        CALL print_teletype_stringB
        RET
        move_char_for_D_into_AL_to_print:
        MOV AL, 0x44
        CALL print_teletype_stringB
        RET
        move_char_for_E_into_AL_to_print:
        MOV AL, 0x45
        CALL print_teletype_stringB
        RET
        move_char_for_F_into_AL_to_print:
        MOV AL, 0x46
        CALL print_teletype_stringB
        RET
于 2018-04-17T20:01:29.500 に答える