我试着寻找答案,而且任何相似的例子都太简单或太复杂。我使用Paul Carter的书作为集会课,所以有些宏来自他。即,print_string,print_int和print_nl函数。
鉴于这个汇编片段:
segment .data
output db "Welcome!",0
string1 db "greater than",0
string2 db "less than",0
string3 db "equal to",0
var_a dd 0Ah
segment .bss
segment .text
global _asm_main
_asm_main:
enter 0,0 ; setup routine
pusha
;***************CODE STARTS HERE***************************
mov eax, output
call print_string
call print_nl
cmp dword[var_a], 0Ah
jle label1
mov eax, string1
call print_string
call print_nl
jmp label3
label1:
cmp dword[var_a], 9h
jg label2
mov eax, string2
call print_string
call print_nl
jmp label3
label2:
mov eax, string3
call print_string
call print_nl
label3:
cmp dword [var_a], 0
jle label4
sar [var_a], 1
mov eax, dword [var_a]
call print_int
call print_nl
jmp label3
label4:
;***************CODE ENDS HERE*****************************
popa
mov eax, 0 ; return back to C
leave
ret
输出为:
欢迎!
equal to
5
2
1
0
我的问题:
我看到它最终如何通过比较获得label2,打印"等于"消息和新行。在那之后,我看到label2中没有额外的比较。那时,label3甚至被调用了?该计划如何离开" LABEL2?我理解程序集中的所有内容,除了在label2的末尾(打印"等于")和label3的开头(它循环移位并打印数字)之间。我错过了什么吗?
执行label2后,程序的控制权是否会回到label1首次调用label2的位置?或者label3是否执行,因为它接下来是顺序的?
答案 0 :(得分:2)
想象一下,您的代码根本没有标签。机器将在列表中逐个执行指令。添加标签根本不会改变这种行为;除非有跳跃,否则机器仍然会转到下一条指令。
标签给出了内存地址的名称。它们在跳跃时很有用。如果我们没有标签,那么我们可能需要这样做:
add foo, bar
sub foo, bar
mul foo, bar
jmp -2 ; Fake code for "go up 2 instructions"
使用标签,我们可以为指令的内存地址命名:
add foo, bar
thingamajig: ; This label equals the address of the 'sub' instruction
sub foo, bar
mul foo, bar
jmp thingamajig