Em assembly x86, tanto JMP quanto CALL transferem controle para outra localização de código, mas seu comportamento de pilha cria semânticas de fluxo de controle fundamentalmente diferentes. Entender esta distinção é essencial para escrever sub-rotinas, implementar recursão e depurar fluxo de controle.
| Aspecto | JMP destino | CALL destino |
|---|---|---|
| Efeito na Pilha | Nenhum — pilha inalterada | Empilha endereço de retorno (EIP/RIP) |
| Mecanismo de Retorno | Nenhum — transferência unidirecional | RET desempilha endereço, retoma após CALL |
| Uso Típico | Loops, condicionais, branches incondicionais | Sub-rotinas, funções, procedimentos |
| Suporte a Aninhamento | Não — não pode aninhar limpo | Sim — pilha permite aninhamento arbitrário |
| Recursão | Impossível sem gestão manual da pilha | Suporte nativo via stack frames |
; Variantes JMP EB cb JMP rel8 ; Salto curto (-128 a +127 bytes) E9 cw JMP rel16/32 ; Salto próximo (relativo) FF /4 JMP r/m16/32/64 ; Salto indireto (registrador/memória) EA cd JMP ptr16:16/32 ; Salto longo (segmento:offset) - legado ; Variantes CALL E8 cw CALL rel16/32 ; Chamada próxima (relativa, empilha RIP) FF /2 CALL r/m16/32/64 ; Chamada indireta 9A cd CALL ptr16:16/32 ; Chamada longa (legado)
; Antes do CALL RIP = endereço da próxima instrução RSP = ponteiro de pilha atual ; CALL alvo executa: 1. RSP ← RSP - 8 ; Decrementa ponteiro de pilha (64-bit) 2. [RSP] ← RIP ; Empilha endereço de retorno (próxima instrução) 3. RIP ← alvo ; Salta para sub-rotina ; Dentro da sub-rotina (prólogo típico): PUSH RBP ; Salva base pointer do chamador MOV RBP, RSP ; Estabelece novo frame pointer SUB RSP, N ; Aloca espaço de pilha local ; Execução RET: 1. RIP ← [RSP] ; Desempilha endereço de retorno 2. RSP ← RSP + 8 ; Restaura ponteiro de pilha 3. Execução retoma após CALL
; JMP alvo executa: 1. RIP ← alvo ; Salto incondicional ; Ponteiro de pilha (RSP) inalterado ; Nenhum endereço de retorno armazenado ; Nenhuma forma de retornar automaticamente
; Chamador CALL calculate_sum ; Empilha endereço retorno, salta ; ... retoma aqui após RET ; Sub-rotina calculate_sum: PUSH RBP MOV RBP, RSP ; ... computação ... MOV RAX, resultado POP RBP RET ; Desempilha endereço retorno, salta de volta
state_loop: CMP AL, 'A' JE handle_A CMP AL, 'B' JE handle_B JMP default_handler handle_A: ; ... processa A ... JMP next_char handle_B: ; ... processa B ... JMP next_char default_handler: ; ... erro ... JMP next_char next_char: ; ... busca próximo ... JMP state_loop ; Volta ao loop
Compiladores às vezes substituem sequência CALL ... RET por JMP quando a última ação de uma função é chamar outra função:
; Sem otimização foo: CALL bar RET ; Com otimização tail call (TCO) foo: JMP bar ; Reutiliza stack frame do chamador
Benefícios: Economia de espaço na pilha, retorno mais rápido. Requer: sem limpeza após chamada, mesma convenção de chamada.
RET — CALL cria endereços de retorno previsíveisCALL/RETRET)Toda chamada de função de alto nível (func() em C, def em Python, method() em Java) compila para maquinaria CALL/RET. Todo while, for, if, goto compila para variantes JMP. A pilha é o que torna CALL poderosa — e o que torna buffer overflows perigosos.
Tecnologia Eletrônica © [www.351231.com]