Как использовать cmp для сравнения двух литералов - PullRequest
0 голосов
/ 16 марта 2020

Моя цель состоит в том, чтобы создать игру с высоким / низким уровнем, в которой мой компьютер делает простой расчет на полпути между двумя последними возможными числами, которые могут быть. Он спрашивает: "Мне становится теплее?" То, что мне нужно, чтобы это заработало (и я не знаю, является ли это указанием nasm c или чем-то подобным), это знание того, почему инструкция cmp не работает. Я пробовал несколько ответов, и они не работают.

Я пытался использовать

mov r8w, 'Y'

Я также пытался

mov r8w, 59h

Оба для сравнения с регистром слов r8w. Я хочу знать, где в моем коде я пропускаю логи c. Вот код.

.loop:

        mov rax, 1
        mov rdi, 1
        mov rsi, hot_cold
        mov rdx, w_len
        syscall

        mov r9w, 0
        mov rax, 0              ; setup for input
        mov rbx, 0              ;
        mov rdi, 2              ;
        mov si, r9w             ; collect input
        syscall                 ; init collection

        mov r8w, 0              ;
        mov r8w, 'Y'            ; 59h
        cmp r9w, r8w            ; compare to Y
        jne .hop_no             ; compare fail, try N
        jmp _for_y              ; compare success, change numbers
        ;syscall
        jmp .loop               ; loop on successful Y

.hop_no:
        mov r8w, 0
        mov r8w, 'N'            ;4Eh
        cmp r8w, r9w            ; compare to N
        jne _exit               ; compare fail, exit
        call _for_n             ; compare success change numbers
        ;syscall                                                                                                                                                                                                           
        jmp .loop

1 Ответ

1 голос
/ 16 марта 2020

Два литерала ? Как в значениях постоянной времени сборки, таких как 1234 или 'Y'? Обычно это бесполезно, потому что вы можете просто выяснить результат самостоятельно или использовать %if, чтобы позволить ассемблеру сделать это во время сборки. т.е. оптимизировать cmp вместо написания инструкций, которые устанавливают и читают FLAGS.

Но если вы настаиваете, cmp может принять не более одного непосредственного операнда, поэтому mov - немедленно передаст другое константное число в регистр first.

    mov  eax, 'Y'
    cmp  AL, 'Y'

Устанавливает флаги:

  • ZF = 1, потому что 'Y' - 'Y' = 0
  • CF = OF = 0, потому что нет заимствовать и без переполнения со знаком
  • SF = 0

(также пишутся PF и AF.)


re: ваш фактический код, который пытается Сравните результат ввода-вывода переменной времени выполнения с целочисленной литеральной константой 'Y'

Похоже, вы думаете, что вы можете read байтов в регистре. Это не вариант. Системного вызова, эквивалентного getchar, не существует. mov si, r9w копирует содержимое (оставляя старшие 6 байтов RSI неизменными), не устанавливая SI = адрес R9W. Регистры не имеют адресов .

Считать в буфер (например, в стек) и затем загрузить его в регистр. Как читать входные данные из STDIN в сборке x86_64? Или использовать cmp с операндом памяти.

Используйте strace ./my_program, чтобы увидеть, какие системные вызовы вы делаете и какой код ошибки или успех они возвращают.

64-битное соглашение о вызовах не передает аргумент в RBX. Я думаю mov rbx, 0 это опечатка для mov edx, 2. (Кажется, у вас тоже есть длина и аргументы FD.) Вы хотите RDI = fd = 0, RDX = length = 2. (Или больше, если пользователь вводит более длинную строку).

RSI должен указывать на память для read(int fd, void *buf, size_t len). У вас есть старшие 6 байтов RSI, установленные с адреса hot_cold, но младшие 2 байта установлены в ноль при копировании r9w без видимой причины. Это может заставить его вернуться -EFAULT, или вы просто пишете куда-то еще в вашем .data разделе.

...