装配自动跳转到下一个标签

时间:2017-05-03 17:30:01

标签: assembly x86 x86-64

我已经在程序集中编写了一个看起来像这样的程序:

%macro print 1

    push rbp

    mov rdi, %1
    xor rax, rax

    call _printf

    pop rbp

%endmacro    
section .data
    e db 'Equal', 0
    l db 'Less than', 0
    g db 'Greater than', 0
section .text
        global start
        extern _printf
    start:
        mov rax, 5
        mov rbx, 5
        cmp rax, rbx ; Compare 4 and 5
        je _equal ; je = jump if equal
        cmp rax, rbx
        jl _less ; jl = jump if less
        cmp rax, rbx
        jg _greater ; jg = jump if greater

        ret

_equal:
    print e
_less:
    print l
_greater:
    print g

但是当我运行该程序时,它会跳转到_equal,但它会跳转到_less_greater。如何禁用此自动跳转?

2 个答案:

答案 0 :(得分:4)

use this

       try:
        fil = open("/Volumes/Melinas SSD/Users/Melina/Desktop/Python/melinas.txt", "w")
    except:
        print('the file cannot be opened')

for highscore in self.highscoreList: 


print('hello')
            file.write(highscore)
            file.write("hej")

这是写mov rax, 5 的低效方式。如果您只将32位值移动到64位寄存器中,则不需要将64位寄存器指定为操作数。只需指定32位寄存器和the upper 32 bits will be implicitly zeroed

同样的事情:

mov eax, 5

您只需编写xor rax, rax ,并将高32位隐式置零。

xor eax, eax

由于您知道只是比较32位值,因此可以编写cmp rax, rbx ; Compare 4 and 5 来仅比较较低的32位半。这更小,更有效。如果您确实想要比较这些寄存器中的整个64位值,则只需要cmp eax, ebx

当然,整个代码有点傻,因为你已经知道4与5相比如何 - 这不需要在运行时执行。

但是,让我们假设这些是运行时值,而 需要进行比较。您仍然只需要进行一次比较。所以这段代码:

cmp rax, rbx

可以简化为:

cmp rax, rbx ; Compare 4 and 5
je _equal ; je = jump if equal
cmp rax, rbx
jl _less ; jl = jump if less
cmp rax, rbx
jg _greater ; jg = jump if greater

因为条件跳转指令不会改变标志。

  

但是当我运行该程序时,它会跳转到cmp rax, rbx je _equal jl _less jg _greater ,但它会跳转到_equal_less。如何禁用此自动跳转?

正如在评论和另一个答案中已经指出的那样,它实际上并不是,因为它没有跳过任何指令。它刚刚落到下一个标签上。

防止这种情况的一种方法 - 如user3344003建议的 - 是在每种情况之后添加无条件跳转指令。类似的东西:

_greater

实际上,你所做的一切都是跳回来。单个 cmp rax, rbx je _equal jl _less jg _greater finished: ret _equal: print e jmp finished _less: print l jmp finished _greater: print g jmp finished 指令的大小小于ret指令,并且由于不需要采用分支,因此更有效。如果在返回之前需要运行一堆清理代码,则只能使用此模式。在这个简单的例子中,你可以这样做:

jmp

请注意,我在 cmp rax, rbx je _equal jl _less jg _greater _equal: print e ret _less: print l ret _greater: print g ret 指令后省略了ret。你并不需要它 - 相等,更少,更详尽地涵盖了所有可能性,因此保证三个分支中的一个被保留。事实上,这意味着您可以重新排列代码以消除其中一个分支,利用最初令您困惑的堕落:

jg

有趣的事实:this is essentially identical to the code that GCC would generate if you'd written this in C

答案 1 :(得分:1)

您需要在每个案例后放置一个跳转指令(打印宏扩展)。它刚刚落下,而不是跳跃。