Linguagem de Montagem
Linguagem de Montagem
Correção Exercício
extern printf, scanf
segment .data
//dados inicializados
segment .bbs
/dados não inicializados
segment .text
//programa principal
extern printf, scanfsegment .data//dados inicializadossegment .bbs/dados não inicializadossegment .text
global mainmain:
enter 0,0// ...leaveret
Exercício
• Escrever um procedimento chamado locate, este deve localizar um caractere em uma dada string.
• O procedimento recebe como parâmetro o caractere a ser localizado, a string e a primeira posição em que começa a busca.
Exercício
• Quando o caractere é encontrado é retornado a posição deste na string, se tal caractere não for encontrado deverá ser retornado um valor negativo.
• O programa principal deverá chamar o procedimento e informar todas as posições que o dado caractere ocorre na palavra, caso não ocorra nenhuma vez ele deve exibir uma mensagem.
extern printf, scanf
segment .data
string db “Isto eh uma strig”,0
letra db “s”
formato db “%d”
msg db “letra não encontrada”,0
segment .text
global main
main:
enter 0,0
// ...
leave
ret
extern printf, scanfsegment .data string db “Isto eh uma strig”,0
letra db “s”formato db “%d”msg db “letra não encontrada”,0
segment .textglobal mainmain:
enter 0,0;EBX contém primeiro endereçomov EBX, string;AL contém letramov AL,[letra];chamar procedimento com os parâmetroscall locate
leaveret
segment .textglobal mainmain: enter 0,0 ;EBX contém 1o. endereço mov EBX, string ;AL contém letra mov AL,[letra] ;chamar procedimento call locate leaveret
locate: ;EBX contém endereço da string ;AL contém caractere ;AH contém posição
repeat : cmp byte [EBX],AL
je achou inc AH inc EBX cmp byte [EBX],0 jne repeat achou: ret
Exercício
• Até agora acha a primeira letra.
• Escrever um procedimento chamado locate, este deve localizar um caractere em uma dada string.
• O procedimento recebe como parâmetro o caractere a ser localizado, a string e a primeira posição em que começa a busca.
Exercício
• Quando o caractere é encontrado é retornado a posição deste na string, se tal caractere não for encontrado deverá ser retornado um valor negativo.
• O programa principal deverá chamar o procedimento e informar todas as posições que o dado caractere ocorre na palavra, caso não ocorra nenhuma vez ele deve exibir uma mensagem.
segment .textglobal mainmain: enter 0,0 ;EBX contém 1o. endereço mov EBX, string ;AL contém letra mov AL,[letra] ;chamar procedimento call locate leaveret
locate: ;EBX contém endereço da string ;AL contém caractere ;AH contém posição
repeat : cmp byte [EBX],AL
je achou inc AH inc EBX cmp byte [EBX],0 jne repeat achou: ret
Exercício
• Quando o caractere é encontrado é retornado a posição deste na string, se tal caractere não for encontrado deverá ser retornado um valor negativo.
• O programa principal deverá chamar o procedimento e informar todas as posições que o dado caractere ocorre na palavra, caso não ocorra nenhuma vez ele deve exibir uma mensagem.
segment .text
global main
main:
enter 0,0
;EBX contém 1o. endereço
mov EBX, string
;AL contém letra
mov AL,[letra]
;chamar procedimento
call locate
push EBX
push ECX
push EAX
;escreve posição push AH push dword formato call printf add esp, 5 pop EAX pop ECX pop EBXleaveret
locate:
segment .textglobal mainmain: enter 0,0 mov EBX, string mov AL,[letra]
proximo: call locate push EBX push ECX push EAX ;escreve posição push AH push dword formato call printf add esp, 5
pop EAX pop ECX pop EBX
cmp byte [EBX],0 je fim
inc EBX inc AH jmp proximo fim:
leaveret
locate: ...
Conteúdo
• Passagem de Parâmetros– Método da Pilha
• Anteriormente: – Método do Registrador
• Prova dia 03/12
Pilha e Procedimento
• Procedimentos são mecanismos que facilitam a programação modular.
• As pilhas desempenham um papel importante na chamada e execução de procedimentos.
• Uma pilha é uma entrada de dados do tipo LIFO.
• PUSH e POP
Registradores
• EIP (Instruction Pointer)– aponta para próxima instrução, possui o
valor de deslocamento (offset) do código da próxima instrução a ser executada.
Implementação da Pilha
• O espaço de memória reservado no segmento de pilha é utilizado para implementar a pilha.
• Os registradores SS e ESP são utilizados para implementar uma pilha no Pentium.
• O topo da pilha que aponta para o último item inserido que é indicado por SS:ESP
Sobre pilha
• O registrador de segmento SS – utilizado para identificar a área de memória
que será usada como pilha.– Aponta para o inicio do segmento da pilha
• ESP – fornece o endereço offset do último item
inserido.
• TOS = topo da pilha
Implementação Pentium
• Apenas words (16-bits) ou doublewords (32-bits) são salvos na pilha, nunca um único byte
• A pilha cresce em direção ao endereço de memória mais baixo.
• TOS aponta para o último item colocado na pilha, aponta para o byte mais baixo da última word inserida.
•Pilha vazia com 256 bytes de memória reservados para realizar operações na pilha.
•Quando a pilha é inicializada, TOS aponta para o byte seguinte a area reservada para a pilha. •Ler de uma pilha vazia causa o erro que chamamos de stack underflow.
Quando uma word é colocada na pilha, ESP é decrementado de 2, e a word é armazenada em SS:ESP.
Como o Pentium usa a ordenação de bytes little-endian, o byte de ordem mais alta é armazenado no endereço mais alto.
Funcionamento da Pilha
• A condição de pilha cheia é indicada pelo valor offset igual a 0 (ESP = 0).
• Se tentarmos inserir um item em uma pilha cheia ocorre stack overflow.
• Recuperar um dado de 32-bits da pilha causa um aumento de 4 no valor offset, este apontando então para o próximo item da pilha.
• A memória retém seus valores. • TOS é atualizado
Método da Pilha
• Neste método todos os parâmetros são colocados na pilha antes do procedimento ser chamado.
push [number1]
push [number2]
call sum
Método da Pilha
n1
n2
Endereço de retorno (EIP)
TOSSP
push n1push n2call sum
Após executar a instrução call, que automaticamente coloca o conteúdo de EIP na pilha temos uma pilha como mostrada na figura ao lado.
Método da Pilha
n1
n2
Endereço de retorno
TOSSP
Os valores de n1 e n2 estão enterrados dentro da pilha
Devemos retirar o valor de EIP antes de ler os dois valores passados.
pop EAXpop EBXpop ECX
Como removemos o endereço de retorno (EIP) da pilha, devemos colocá-lo de volta utilizando para isso um push EAX.
Método da Pilha
• Problema deste código:– Usa registradores para copiar os valores dos
parâmetros, o que significa que o procedimento não poderá utilizar estes registradores para nenhum outro propósito.
• Solução – Copiar os parâmetros da pilha para variáveis
locais, mas isso é totalmente ineficiente.
Método da Pilha
n1
n2
Endereço de retorno ESP
ESP+4
ESP+6
• A melhor forma de pegar os parâmetros é deixá-los na pilha e lê-los diretamente da pilha quando necessário.
• A pilha é uma seqüência de espaços na memória.
Método da Pilha
n1
n2
Endereço de retorno ESP
ESP+4
ESP+6
MOV EBX,[ESP+4] pode ser usado para ler n2
Problema: O ponteiro da pilha é atualizado através das operações push e pop, como resultado, o offset relativo muda com as operações na pilha feitas pelo procedimento chamado.
Método da Pilha
n1
n2
Endereço de retorno EBP
ESP
Solução:Usar o registrador EBP ao invés de ESP para especificar o offset dentro do segmento da pilha.
mov EBP,ESPmov AX,[EBP+4]
EBP+4
EBP+8
Método da Pilha
• Esta é a forma usual de se acessar parâmetros da pilha.
• Já que todo procedimento usa o registrador EBP para acessar os parâmetros, o registrador EBP deverá ser preservado. – Devemos salvar o conteúdo do registrador EBP,
antes de fazermos o MOV, usando a pilha para isto. – Note que mov EBP,ESP faz com que o parâmetro de
deslocamento aumente de quatro bytes
Método da Pilha
n1
n2
Endereço de retorno
EBP EBPESP
push EBPmov EBP,ESPmov AX,[EBP+8]
EBP+4
EBP+8
EBP+10
Método da Pilha
• stack frame(moldura da pilha) = informação armazenada na pilha– parâmetros, – endereço de retorno, – valor antigo de EBP
• A stack frame também consiste de variáveis locais caso o procedimento as use.
Método da Pilha
• O valor EBP é referenciado como frame pointer(FP).
• Uma vez que o valor de EBP é conhecido, podemos acessar todos os itens na moldura da pilha.
• Antes de retornar do procedimento devemos lembrar de fazer um pop EBP para restaurar o valor original de EBP.
• A instrução ret faz com que o endereço de retorno seja armazenado no registrador EIP.
Método da Pilha
• Os quatro bytes da pilha ocupados pelos dois parâmetros não tem mais uso.
• Uma forma de liberar estes quatro bytes é incrementar ESP em quatro após a instrução call.
push number1push number2call sumadd ESP,4
Passagem de Parâmetro pela Pilha; Entrada: Dois inteiros dado pelo usuário.; Saída: Soma dos dois inteiros, colocado em AX.segment .bbs n1 resw 1
n2 resw 1
segment .text;ler n1 e n2
mov CX,[n1] mov DX, [n2] push CX ; coloca primeiro número na pilha push DX ; coloca segundo número na pilha call sum ; retorna soma em AX
; escreve resultado em AX
Passagem de Parâmetro pela Pilha
segment .text;ler n1 e n2
mov CX,[n1] mov DX, n2 push CX
push DX
call sum
CX/n1
DX/n2
Endereço de retorno
EBPESP
EBP+4
EBP+8
Passagem de Parâmetro pela Pilha
;------------------------------------------------;Recebe dois inteiros via pilha.;O resultado é retornado em AX.;------------------------------------------------sum:
push EBP ; salva EBP mov EBP, ESP
mov AX,[EBP+10] ; sum = n1add AX,[EBP+8] ; sum = sum + n2
pop EBP ; restaura EBPret ; retorna
CX/n1
DX/n2
Endereço de retorno
EBP EBPESP
EBP+4
EBP+8
EBP+10
Passagem de Parâmetro pela Pilha; Entrada: Dois inteiros dado pelo usuário.; Saída: Soma dos dois inteiros, colocado em AX.segment .bbs n1 resw 1
n2 resw 1
segment .text;ler n1 e n2
mov CX,[n1] mov DX, n2 push CX ; coloca primeiro número na pilha push DX ; coloca segundo número na pilha call sum ; retorna soma em AX add ESP,4
; escreve resultado em AX
Exercício
• Escreva um procedimento chamado MAX que receba três inteiros do programa principal e retorne o máximo dos três em AX. O programa principal deve pedir ao usuário que entre os três inteiros e mostrar na tela o maior deles utilizando para isso o procedimento MAX.