代码之家  ›  专栏  ›  技术社区  ›  Cabralito

为什么即使进行了正确的比较,我的Assembly程序在达到值10后仍继续执行?

  •  1
  • Cabralito  · 技术社区  · 6 月前

    我正在用Assembly x86-64编写一个程序,目标是递增一个值(num),直到它达到10。然而,尽管使用了正确的比较来检查num是否小于10,程序仍会继续执行并打印10之后的值:

    [BITS 64]
    default rel
    
    section .data
    extern ExitProcess, printf
        msg db "%d", 10, 0
        num dq 0
    
    section .text
        global main
    
    main:
        sub rsp, 56
    again:
        mov r8, [num]
        add r8, 1
        mov [num], r8
    
        lea rcx, [msg]
        mov rdx, [num]
        call printf
    
        cmp r8, 10
        jge end
    
        jmp again
    
    end:
    
        xor rax, rax
        call ExitProcess
    

    执行此操作将打印:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10 ; <--- ??? don´t stop
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [...]
    

    但当它达到10时应该停止。为什么会这样?

    2 回复  |  直到 6 月前
        1
  •  2
  •   Tom V    6 月前

    登记册 r8 在函数内部被覆盖(“clobbered”) printf 。您需要先从内存中重新加载它,然后再执行 cmp 指令。或者,您可以重新排列代码,以便 cmp 与执行增量的代码一起完成。

        2
  •  -1
  •   Ali Ahmad    6 月前

    出现问题是因为在检查r8是否达到10之前,您正在递增r8。在再次循环中,在将r8的值与cmp r8,10的10进行比较之前,先将r8加上r8,1来增加其值。这导致r8在检查发生之前递增到10,并且程序直到r8递增到10之后才停止。为了解决这个问题,您应该在增量之前执行比较。

    [BITS 64]
    default rel
    
    section .data
    extern ExitProcess, printf
        msg db "%d", 10, 0
        num dq 0
    
    section .text
        global main
    
    main:
        sub rsp, 56
    again:
        mov r8, [num]
        cmp r8, 10       ; Compare num with 10 before incrementing
        jge end          ; Jump to end if num >= 10
        add r8, 1        ; Increment num
        mov [num], r8    ; Store updated num
    
        lea rcx, [msg]
        mov rdx, [num]
        call printf
    
        jmp again
    
    end:
        xor rax, rax
        call ExitProcess
    

    说明:

    cmp r8,10指令现在在递增之前检查r8(包含num的值)是否大于或等于10。 如果r8已经是10,程序将跳到结束标签并停止。

    一旦该值达到10,现在应该停止打印。