Rótulos Locais em Assembly NASM
Em programas Assembly, os rótulos servem para nomear posições específicas no código, facilitando saltos (jmp, je, jne, etc.) e o controle do fluxo de execução.
Uma função pode conter vários rótulos, mas cada nome deve ser único dentro do programa.
Se dois rótulos tiverem o mesmo nome, o montador exibirá um erro de redefinição. Veja o exemplo a seguir, em Linux, onde isso acontece.
Problema com Rótulos Repetidos
global _start
section .data
nums dq 5, 6, 7, 8, 1, 2, 3, 4
numSize equ 8
count equ ($ - nums) / numSize
section .text
_start:
mov rdi, nums
mov rsi, count
call max
mov rdi, rax
mov rax, 60
syscall
; Função min retorna o menor valor do array
; RDI - endereço do array
; RSI - quantidade de elementos
; RAX - resultado
min:
mov rax, [rdi]
jmp condition
while:
dec rsi
cmp rax, [rdi + rsi * numSize]
jb condition
mov rax, [rdi + rsi * numSize]
condition:
cmp rsi, 1
ja while
ret
; Função max retorna o maior valor do array
max:
mov rax, [rdi]
jmp condition
while:
dec rsi
cmp rax, [rdi + rsi * numSize]
ja condition
mov rax, [rdi + rsi * numSize]
condition:
cmp rsi, 1
ja while
retO código define duas funções (min e max), ambas com os rótulos while e condition.
Durante a montagem, o NASM retornará erro:
error: label `while` inconsistently redefined info: label `while` originally defined here error: label `condition` inconsistently redefined info: label `condition` originally defined here
A duplicação ocorre porque o NASM trata rótulos globais como identificadores únicos dentro de todo o programa.
Solução: Rótulos Locais
Para resolver o problema, o NASM permite criar rótulos locais, que são acessíveis apenas dentro do escopo de um rótulo global (como uma função).
Um rótulo local é identificado por um ponto (.) no início do nome.
Exemplo:
.while:
.condition:Esses rótulos são “filhos” do rótulo global que os antecede.
Escopo de um Rótulo Local
func1:
.label1:
func2:
.label2:Neste caso:
.label1pertence afunc1.label2pertence afunc2.label1não pode ser acessado dentro defunc2
Assim, cada função pode ter seus próprios rótulos internos sem risco de conflito.
Exemplo Corrigido com Rótulos Locais
global _start
section .data
nums dq 5, 6, 7, 8, 1, 2, 3, 4
numSize equ 8
count equ ($ - nums) / numSize
section .text
_start:
mov rdi, nums
mov rsi, count
call max
mov rdi, rax
mov rax, 60
syscall
; Função min retorna o menor valor do array
; RDI - endereço do array
; RSI - quantidade de elementos
; RAX - resultado
min:
mov rax, [rdi]
jmp .condition
.while:
dec rsi
cmp rax, [rdi + rsi * numSize]
jb .condition
mov rax, [rdi + rsi * numSize]
.condition:
cmp rsi, 1
ja .while
ret
; Função max retorna o maior valor do array
max:
mov rax, [rdi]
jmp .condition
.while:
dec rsi
cmp rax, [rdi + rsi * numSize]
ja .condition
mov rax, [rdi + rsi * numSize]
.condition:
cmp rsi, 1
ja .while
retAgora, as metainstruções .while e .condition são locais a cada função, e o código compila corretamente.
Como o NASM Interpreta os Rótulos Locais
Internamente, o NASM converte rótulos locais no formato:
nome_global.nome_local
Assim:
.whiledentro da funçãominse tornamin.while.conditiondentro da funçãomaxse tornamax.condition
Por isso, não há conflitos — cada função tem seu próprio espaço de nomes.
É até possível referenciar explicitamente o nome completo de um rótulo local:
max:
mov rax, [rdi]
jmp max.condition ; salto para o rótulo local com nome completo
.while:
dec rsi
cmp rax, [rdi + rsi * numSize]
ja max.condition
mov rax, [rdi + rsi * numSize]
.condition:
cmp rsi, 1
ja max.while
retIsso deixa claro que os rótulos locais são apenas atalhos para nomes compostos.
Resumo
- Cada programa NASM pode conter apenas um rótulo global com determinado nome.
- Rótulos locais começam com
.e são visíveis apenas dentro do escopo do rótulo global anterior. - Internamente, o NASM os converte em
rótulo_global.rótulo_local. - Isso evita conflitos de nomes e torna o código modular e mais organizado.
- Rótulos locais são especialmente úteis para estruturas repetitivas, como loops e condições dentro de funções.