1

名前が印刷される回数を示すために使用される入力用に2桁の数字を許可する必要があります。ただし、2桁目を分離して、0x30と0x39の間にあることを確認する方法がわかりません。また、その中に0017が含まれている名前の後にこの奇妙なボックスが表示され続けます。

    .data   
    input_msg_len:  .long 26
    input_msg:  .ascii "Enter a two-digit number: "
    name:       .ascii "Michael Chabon\n"
    name_len:   .long 16
    max:        .long 0
    count:      .long 0
    tmp:        .long 0
    input_str:  .ascii "??" 

    .text               
    .global _start          
    _start:     
        mov $4, %eax    
        mov $1, %ebx
        mov $input_msg, %ecx
        mov input_msg_len, %edx
        int $0x80

        mov $3, %eax    
        mov $0, %ebx    
        mov $input_str, %ecx 
        mov $2, %edx    
        int $0x80   

        mov $input_str, %eax
        add count, %eax

            mov $input_str, %eax 
        mov (%eax), %bl 
        cmp $0x30, %bl  
        jl  _start      
        cmp $0x39, %bl  
        jg  _start  

        mov count, %eax 
        inc %eax        
        mov %eax, count 

        sub $0x30, %bl
        mov %bl, max

        mov $10, %bl    
        imul    %bl
        mov %bl, max

#Not sure how to check second char in input_str.
#Want to check it then subtract $0x30 and move to tmp before adding tmp to max.

        mov $0, %edi    
    again:
        cmp max, %edi   
        je  end     

        mov $4, %eax    
        mov $1, %ebx    
        mov $name, %ecx
        mov name_len, %edx
        int $0x80       

        inc %edi        
jmp again       


    end:
        mov $1, %eax    
        int $0x80       

前もって感謝します!

4

1 に答える 1

0

コードにいくつかのバグがあります。

以下では、とにかくmov $input_str, %eax上書きするため、そのブロックの最初の2行は冗長です。eax

    mov $input_str, %eax
    add count, %eax

    mov $input_str, %eax

count次に、ここにロードするのは意味がありませんeax

    mov count, %eax 
    inc %eax        
    mov %eax, count

これは、次の方法ではるかに短く明確な方法で行うことができます。

    incl count

次に、次のバグは、に最近ロードcountした後、ロードされeaxたの下位8ビットに10を掛けることです。このコードでは、次のようになります。countal

    mov (%eax), %bl  // bl = first character
    cmp $0x30, %bl  
    jl  _start      
    cmp $0x39, %bl  
    jg  _start  

    mov count, %eax // eax = count
    inc %eax        // eax++
    mov %eax, count // count = eax

    sub $0x30, %bl  // 0 <= bl <= 9
    mov %bl, max    // max = bl <- you lose this value in the next mov %bl, max

    mov $10, %bl    // bl = 10
    imul    %bl     // ax = 10 * and(count, 0xff) // ax = al*bl (signed multiply)
    mov %bl, max    // max = 10 <- here you overwrite the value of max with 10

だから、私の直感によれば、あなたはやりたくないax = 10 * and(count, 0xff)のですが10 * (first number)imul %bloはとの間alで乗算を行いbl、結果を。に格納しaxます。したがって、上記のコードは次のように変更できます。

    mov (%eax), %bl  // bl = first character
    cmp $0x30, %bl  
    jl  _start      
    cmp $0x39, %bl  
    jg  _start  

    incl count

    pushl %eax      // push eax to stack

    sub $0x30, %bl  // 0 <= bl <= 9
    mov $10, %al    // al = 10
    imul     %bl    // ax = 10 * bl (signed multiply)
    mov %al, max    // 0 <= max <= 90

次に、最初の文字と同様に2番目の文字を確認できます。

    pop %eax        // pop eax from stack

    incl %eax

    mov (%eax), %bl  // bl = second character
    cmp $0x30, %bl  
    jl  _start      
    cmp $0x39, %bl  
    jg  _start

    sub $0x30, %bl  // 0 <= bl <= 9

    add %bl, max    // 0 <= max <= 99

デバッガーの使い方を学ぶことを強くお勧めします。gdbにはいくつかのフロントエンドがありますが、私の経験によれば、dddが最適に機能すると思います。gdbtuiも便利です。

于 2013-03-10T01:06:40.967 に答える