X86 - 功能未定义

时间:2016-10-28 17:02:38

标签: assembly x86

我是程序员的新手,我正试图在x86中绕过函数调用。我提供了以下代码:

read_integer:

push ebp        
mov ebp, esp    

sub esp, 8 
mov dword [ebp-4], '0' 
mov dword [ebp-8], 0 

push ebx        
push ecx        
push edx        

.read_loop:
mov eax, 10     
mul dword [ebp-8] 
add eax, [ebp-4] 
sub eax, '0'    
mov [ebp-8], eax

mov eax, 3 
mov ebx, 0 
lea ecx, [ebp-4]
mov edx, 1 
int 0x80   

cmp dword [ebp-4], 10 
jne .read_loop  

ret 

我可以使用read_integer调用call read_integer函数。但是,当我尝试使用.read_loopcall .read_loop执行相同操作时,我收到错误:

  

.read_loop未定义。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

.read_loop中的点表示标签为 local

只能在同一范围内看到#34;由2个全球标签组成。

global_label_1:
    code
.local_label
    code
    jne .local_label  <=== no ambiguity, the label is locally defined, jumps to the label above
global_label_2:
   code
.local_label    <=== same name but different scope
   code

它非常有用,因为代码可以在不同的过程中多次复制/粘贴,而不会出现命名冲突。

在您的情况下,删除前导点将解决它:您希望它是全局的。

read_loop:
mov eax, 10
...
call read_loop    
编辑:一些汇编程序也允许访问内部标签:call read_integer.read_loop

答案 1 :(得分:1)

.read_loop并非call。它是标记循环开始的read_integer的本地标签。

如果你看一下read_integer的结尾,你会看到:

cmp dword [ebp-4], 10 
jne .read_loop  

只要.read_loop不等于10,它就会跳回[ebp-4]。这与你在C中写下以下内容类似:

do {
  // Whatever
} while (*(ebp-4) != 10);

为了能够跳转某个地方你需要指定 来跳转。对位置进行硬编码会非常不方便,因此您使用标签并让汇编程序找出该标签对应的地址。
但您可能只希望某些标签在特定范围内可见(例如在read_integer内)。也许你希望能够在其他一些函数中使用相同的标签名称,或者你只是想让那些正在阅读代码的人明白该标签是函数的本地标签。因此,一些汇编程序提供了使标签本地化的语法,如@ Jean-FrançoisFabre所述。

有些汇编程序更进一步,允许使用“匿名”标签,例如:

1:
    jmp 2f   ; f for forwards
    ; Whatever
    jmp 1b   ; b for backwards
2:

或者:

-:
    jp +  ; this is Z80 assembly, so jp isn't a typo
    ; Whatever
    jp -
+: