我已经在程序集中编写了一个看起来像这样的程序:
%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
。如何禁用此自动跳转?
答案 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)
您需要在每个案例后放置一个跳转指令(打印宏扩展)。它刚刚落下,而不是跳跃。