【问题标题】:How to use cmp to compare two literals如何使用 cmp 比较两个文字
【发布时间】:2020-03-16 03:04:36
【问题描述】:

我的目标是创建一个高/低游戏,让我的计算机在最后两个可能的数字之间进行简单的计算。它问:“我变热了吗?”我需要让它继续运行(我不知道这是否是特定于 nasm 的东西)是知道为什么 cmp 指令不起作用。我已经尝试了几个答案,但它们都不起作用。

我尝试过使用

mov r8w, 'Y'

我也试过了

mov r8w, 59h

两者都与字寄存器r8w 进行比较。我想知道我的代码在哪里跳过了逻辑。这是代码。

.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

【问题讨论】:

  • @PeterCordes 好的,所以(strace 很棒)EFAULT 正在发生。我说地址不好。我该怎么做才能清除该变量?
  • 您可以阅读我在答案中链接的How to read input from STDIN in x86_64 assembly?
  • 如果指令集不能在一条指令中做某事,那就使用两条或更多条指令!

标签: assembly x86-64 nasm


【解决方案1】:

两个文字?就像 1234'Y' 这样的汇编时间常数值?这通常没用,因为您可以自己计算结果,或者使用%if 让汇编器在汇编时完成。即优化 cmp 而不是编写设置和读取 FLAGS 的指令。

但如果你坚持,cmp 最多只能接受一个立即数操作数,所以mov-首先将另一个常数立即数写入寄存器。

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

这会设置标志:

  • ZF=1 因为'Y' - 'Y' = 0
  • CF=OF=0,因为没有借位,也没有带符号溢出
  • SF=0

(也写PF和AF。)


re:您的实际代码尝试将运行时变量 I/O 结果与整数文字常量 'Y' 进行比较

看起来您认为您可以将read 字节写入寄存器。不是这种情况。没有等效于getchar 的系统调用。 mov si, r9w 复制内容(不修改 RSI 的高 6 字节),不设置 SI = R9W 的地址。 注册者没有地址

读入缓冲区(例如在堆栈上),然后将其加载到寄存器中。 How to read input from STDIN in x86_64 assembly? 或将cmp 与内存操作数一起使用。

使用strace ./my_program 查看您正在进行的系统调用以及它们返回的错误代码或成功。

64 位调用约定不会在 RBX 中传递 arg。我认为mov rbx, 0mov edx, 2 的错字。 (您的长度和 FD 参数似乎也混淆了。)您想要 RDI=fd=0,RDX=length=2。 (或更多,以防用户键入更长的行)。

RSI 需要指向read(int fd, void *buf, size_t len) 的内存。您从hot_cold 的地址设置了 RSI 的高 6 字节,但由于没有明显原因,复制 r9w 将低 2 字节设置为零。这可能会使其返回 -EFAULT,或者您可能只是在您的 .data 部分的其他地方写。

【讨论】:

  • 为什么我现在只是循环播放?我做了你说的一切,但它没有做任何事情。要我更新代码吗?
猜你喜欢
  • 2022-11-13
  • 2014-03-30
  • 2013-03-01
  • 2018-11-29
  • 1970-01-01
  • 2022-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多