Сборка NASM x86 - Проблемы с вводом - PullRequest
3 голосов
/ 10 ноября 2011

Я работаю, чтобы дважды принять ввод от пользователя и сравнить его.Если они одинаковы, программа завершается.Если нет, то он перепечатывает ввод с первого раза и ждет, пока пользователь что-то наберет.Если это то же самое, происходит то же самое, что и раньше.Если нет, то происходит то же самое, что и раньше.

Вход и цикл не являются проблемой.Основная проблема - результат, который я получаю от программы.Вот что я делаю по кодам:Мои чеки работают не так, как предполагалось в приведенном выше коде, и в итоге я даже не могу заставить программу печатать что-либо, кроме новой строки.Есть ли причина для этого?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 10 ноября 2011

Помимо того, на что указывает @Joshua, вы неправильно сравниваете свои строки.

checker:
    mov ebx, check  ; Moves the *address* of check into ebx
    mov ecx, input  ; Similarly for input
    cmp ebx, ecx    ; Checks if the addresses are the same (they never are)

Во-первых, когда у вас есть, например, label dd 1234 в вашем сегменте данных mov eax, label переместит адрес от label до eax, в то время как mov eax, [label] переместит содержимое , сохраненное в label (в данном случае 1234) в eax.

Обратите внимание, что в вышеприведенном примере я сознательно использовал 32-битную переменную, чтобы она аккуратно вписывалась в eax.Если вы используете переменные байтового размера (например, символы ascii), например, mybyte db 0xfe, вам придется либо использовать регистр байтового размера (al, ah, dh и т. Д.), Либо использовать перемещение с нулем / знакомрасширить коды операций: movzx eax, byte [mybyte] установит значение eax на 254, а movsx eax, byte [mybyte] установит значение eax на -2 (0xfffffffe).

Вам также нужно сделать посимвольное сравнение строк.Предполагая, что вы сохраняете длину строки чтения (вы действительно должны проверять наличие отрицательных возвращаемых значений - то есть ошибок) в input_len и check_len, это может выглядеть примерно так:

    mov eax, [input_len]
    cmp eax, [check_len]
    jne loop       ; Strings of different length, do loop again
    mov ebx, check
    mov ecx, input
.checkloop:
    mov dl, [ebx]  ; Read a character from check
    cmp dl, [ecx]  ; Equal to the character from input?
    jne loop       ; Nope, jump to `loop`
    inc ebx        ; Move ebx to point at next character in check
    inc ecx        ; and ecx to next character in input
    dec eax        ; one less character to check
    jnz .checkloop ; done?

    ; the strings are equal if we reach this point in the code
    jmp done

Если вы заинтересованы вдругой способ сделать это в меньшем количестве инструкций: поиск rep cmpsb.

В коде есть несколько других проблем, следующих непосредственно за вашим checker кодом.Инструкция pop edx (и следующий код, вплоть до метки loop) не будут выполнены, поскольку вы всегда переходите к loop или done.

jne loop    ;if not the same go to input again
je done     ;else go to the end
pop edx   ; Will never be reached!

Причинавы получаете забавные символы из newlineL: db $-newline Это должно быть equ вместо db или вы должны заменить mov edx, newlineL на movzx edx, byte [newlineL].Поскольку newlineL в отличие от других *L имен относится к переменной, а не к константе, equ mov edx, newlineL будет использовать адрес переменной newlineL в качестве количества байтов для записи, когда вы хотите, чтобы оно было 1.

1 голос
/ 10 ноября 2011

Вы предполагаете, что sys.read возвращает всю строку. Это не обязательно. Может возвращаться только после одного символа или даже после части второй строки.

Знаете, такие вещи меня бесят. Это похоже на домашнее задание при написании на ассемблере, но проблема не в сборке, а в предположениях о том, как работают системные вызовы.

Мне бы очень хотелось, чтобы инструкторы предоставили библиотеку fgets для подобных вещей.

В любом случае, глупый способ исправить это - читать по одному байту за раз, ища LF (байт 10), чтобы завершить цикл.

...