使用 64 位寄存器比较 nasm x86-64 中的字符

Comparing a character in nasm x86-64 using 64 bit registers

我是 x86_64 编码新手,正在研究各种代码。

我正在尝试比较 nasm x86_64 代码中的字符 'A' 但比较结果不相等。

; Tests the command line. Similar to a C main function:
;  int main(int argc, char** argv)
;
; - argc, number of args in rdi
; - argv, pointer to pointer in rsi and argv

    global  main
    extern  puts
main:
    mov     rbp, rdi      ; argc in rdi. Save in rbp, caller-saved
    mov     rbx, rsi      ; argv in rsi. Save in rbx, caller-saved
    
    add     rbx, 8
    dec     rbp
    mov     rdi, [rbx]
    cmp     rdi, 'A'
    je      exit1
    call    puts
    mov     rax, 0
    ret

exit1:  
    mov     rax, 1
    ret

如何修改代码才能得到想要的结果? 有解决方案,但它使用此处使用的 8 位寄存器 comparing characters in assembly, nasm,但为了清除我的基础知识,我想了解为什么像我的代码这样的直接比较不起作用。

  • argv 是指向指向 null-terminated 字符串的指针列表的指针。 在顶部,您必须先取消引用指针 mov rbx, [rsi],这样您实际上是在检查 *char 值的列表。

  • cmp 操作数的大小(实际上对于几乎所有指令)都很重要,引用英特尔在 cmp 上的指令参考:

    When an immediate value is used as an operand, it is sign-extended to the length of the first operand.

    您实际上是在比较两个 64 位数量。

  • 有(至少)两种可能的解决方案:

    • cmp dil, 'A': 您仍然可以一次从内存中检索 8 个字节,但出于比较目的,您需要指定一个部分寄存器。
    • cmp之前插入movsx rdi, dil(或者结合一步获取movsx rdi, byte [rbx]): 正如 建议的那样,您仍然可以执行 64 位比较,但要确保高位设置正确。
  • cmp rdi, 'A' 是写 cmp rdi, 0x41 的替代方法。 执行后,0x41 得到 sign-extended,因此您最终将 0x00000041rdi 的内容进行比较。 现在,如果您之前从 [rbx] 加载 8 字节,则前七个字节 可能 充满了乱码,或者说 char 字符串中的 以下 个字符。 给你添麻烦了。

  • 旁注: 说到参数传递,我不确定你是否可以这样调用 putsrdi 不应该包含 null-terminated 字符串的 地址 吗?