Assembly Language for Intel-Based Computers, 5th Edition Kip R. Irvine Chapter 8: procedimentos avançados Slides prepared by Kip R. Irvine Revision date: June 4, 2006 (c) Pearson Education, 2006-2007. All rights reserved. You may modify and copy this slide show for your personal use, or for use in the classroom, as long as this copyright statement, the author's name, and the title are not changed. índice • • • • Stack Frames Recursão INVOKE, ADDR, PROC e PROTO MACROS Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 2 Stack Frames • • • • • Parâmetros de pilha Variáveis locais Instruções ENTER e LEAVE Diretiva LOCAL Procedimento WriteStackFrame Seção seguinte Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 3 Parâmetros de pilha • Mais conveniente que parâmetros de registradores • Duas possíveis formas de chamar DumpMem. Qual é a mais fácil? pushad mov esi,OFFSET array mov ecx,LENGTHOF array mov ebx,TYPE array call DumpMem popad Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. push push push call TYPE array LENGTHOF array OFFSET array DumpMem Web site Examples 4 Stack Frame • Também conhecido como activation record • Área da pilha destinada para o endereço de retorno, passagem de parâmetros, registradores salvos,e variáveis locais • Criado pelos seguintes passos: • O programa chamador salva os argumentos na pilha e chama o procedimento. • O procedimento chamado salva EBP na pilha e carrega o valor de ESP em EBP. •EBP passa a ser base para os parâmetros do procedimento chamado. • Se variáveis locais são necessárias, uma constante é subraída de ESP para abrir espaço na pilha. 5 Web site Examples Acesso explícito a parâmetros de pilha • Um procedimento pode acessar explicitamente parâmetros de pilha usando offset constante em EBP1. • Exemplo: [ebp + 8] • EBP é chamado de base pointer ou frame pointer porque contem o endereço da base do stack frame. • EBP não muda de valor durante a execução do procedimento. • EBP deve ser restaurado com seu valor original quando o procedimento termina. 1 BP in Real-address mode Web site Examples 6 Instrução RET • Retorna da subrotina • Recupera (Pop) o ponteiro de instrução (EIP ou IP). O controle é transferido para o endereço recuperado. • Sintaxe: • RET • RET n • Operando opcional n causa pop de n bytes da pilha após EIP (ou IP) receber o endereço de retorno. Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 7 Exemplo de Stack Frame .data sum DWORD ? .code push 6 push 5 call AddTwo mov sum,eax AddTwo PROC push ebp mov ebp,esp . . ; ; ; ; second argument first argument EAX = sum save the sum 00000006 [EBP + 12] 00000005 [EBP + 8] return address [EBP + 4] Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. EBP EBP, ESP Web site Examples 8 AddTwo Procedure (1 de 2) • Reescrevendo AddTwo Procedure AddTwo PROC, val1:DWORD, val2:DWORD mov eax,val1 add eax,val2 ret AddTwo ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 9 AddTwo Procedure (2 de 2) • MASM gera o seguinte código quando é montado AddTwo (do slide anterior): AddTwo PROC, val1:DWORD, val2:DWORD push ebp mov ebp, esp mov eax,val1 add eax,val2 leave ret 8 AddTwo ENDP A instrução LEAVE resume-se em: mov pop esp,ebp ebp AddTwo PROC, val1:DWORD, val2:DWORD mov eax,val1 add eax,val2 AddTwo ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 10 Passando Argumentos por Referência (1 de 2) • O procedimento ArrayFill preenche um vetor com inteiros aleatórios de 16-bits • O programa chamador passa o endereço do vetor, e o número de elementos: .data count = 100 array WORD count DUP(?) .code push OFFSET array push COUNT call ArrayFill Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 11 Passando Argumentos por Referência (2 de 2) ArrayFill pode referenciar um vetor sem saber o nome : ArrayFill PROC push ebp mov ebp,esp pushad mov esi,[ebp+12] mov ecx,[ebp+8] . . offset(array) [EBP + 12] count [EBP + 8] return address EBP EBP ESI aponta para o início do vetor, para facilitar o uso de um loop para acessar cada elemento. View the complete program. Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 12 Variáveis locais • Para criar variáveis locais explicitamente, subtrair o seu tamanho de ESP. • O seguinte exemplo cria e inicializa duas variáveis locais de 32-bits( locA e locB): MySub PROC push ebp mov ebp,esp sub esp,8 mov [ebp-4],123456h mov [ebp-8],0 . . Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. ; locA ; locB Web site Examples 13 Instrução LEA • A instrução LEA retorna os offsets dos operandos • Mais genérico que o operador OFFSET que pode retornar somente offsets de constantes. • LEA é requerida para a obtenção de offset de um parâmetro de pilha ou variável local. Por exemplo: CopyString PROC, count:DWORD LOCAL temp:BYTE mov mov lea lea edi,OFFSET count esi,OFFSET temp edi,count esi,temp Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. ; ; ; ; invalid operand invalid operand ok ok Web site Examples 14 Sua vez . . . • Criar um procedimento Difference que subtrai o primeiro argumento do segundo. Exemplo: push 14 push 30 call Difference Difference PROC push ebp mov ebp,esp mov eax,[ebp + 8] sub eax,[ebp + 12] pop ebp ret 8 Difference ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. ; first argument ; second argument ; EAX = 16 ; second argument ; first argument Web site Examples 15 Classificação de parâmetros • Parâmetro de entrada é um dado passado do programa chamador para o procedimento. • O procedimento chamado não modifica o parâmetro. A modificação é confinada somente dentro do procedimento. • Um parâmetro de saída é criado passando um ponteiro a uma variável quando um procedimento é chamado. • O procedimento não usa o valor existente na variável, mas coloca um novo valor antes do retorno. • Um parâmetro de entrada-saída é um ponteiro para uma variável contendo uma entrada que será usada e modificada pelo procedimento. • A variável passada pelo programa chamador é modificada. Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 16 Exemplo: trocando dois inteiros O procedimento Swap troca valores de dois inteiros de 32 bits. pValX e pValY não trocam valores, mas os inteiros que eles apontam são modificados. Swap PROC USES eax esi edi, pValX:PTR DWORD, ; pointer to first integer pValY:PTR DWORD ; pointer to second integer mov esi,pValX mov edi,pValY mov eax,[esi] xchg eax,[edi] mov [esi],eax ret Swap ENDP ; get pointers ; get first integer ; exchange with second ; replace first integer Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 17 ENTER e LEAVE • Instrução ENTER cria um stack frame para um procedimento chamado: tem dois operandos sendo o primeiro o número de bytes e o segundo o nível de “aninhamento” (nesting level) • salva EBP na pilha e novo EBP aponta para a base do stack frame • Reserva espaço para variáveis locais • Exemplo: MySub PROC enter 8,0 • Equivale a: MySub PROC push ebp mov ebp,esp sub esp,8 Web site Examples 18 Diretiva LOCAL • Uma variável local é criada, usada, e destruída dentro de um procedimento • A diretiva LOCAL declara uma lista de variáveis locais • Segue imediatamente à diretiva PROC • É atribuído um tipo a cada variável • Sintaxe: LOCAL varlist Exemplo: MySub PROC LOCAL var1:BYTE, var2:WORD, var3:SDWORD LOCAL substitui ENTER, atribuindo nomes às variáveis locais Web site Examples 19 Exemplo de LOCAL (1 de 2) BubbleSort PROC LOCAL temp:DWORD, SwapFlag:BYTE . . . ret BubbleSort ENDP MASM gera o seguinte código: BubbleSort PROC push ebp mov ebp,esp add esp,0FFFFFFF8h . . . mov esp,ebp pop ebp ret BubbleSort ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. ; add -8 to ESP Web site Examples 20 Exemplo de LOCAL (2 de 2) Diagrama do stack frame para o procedimento BubbleSort: return address EBP ESP EBP temp [EBP - 4] SwapFlag [EBP - 8] Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 21 Variáveis locais Non-Doubleword • Variáveis locais podem ser de diferentes tamanhos • Como são criadas numa pilha com a diretiva LOCAL: • 8-bit: no próximo byte da pilha • 16-bit: no próximo word da pilha • 32-bit: no próximo doubleword da pilha Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 22 Local Byte Variable Example1 PROC LOCAL var1:BYTE mov al,var1 ret Example1 ENDP ; [EBP - 1] Web site Examples 23 Procedimento WriteStackFrame • Mostra o conteúdo do stack frame corrente • Protótipo: WriteStackFrame PROTO, numParam:DWORD, ; number of passed parameters numLocalVal: DWORD, ; number of DWordLocal variables numSavedReg: DWORD ; number of saved registers Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 24 Exemplo de WriteStackFrame main PROC mov eax, 0EAEAEAEAh mov ebx, 0EBEBEBEBh INVOKE aProc, 1111h, 2222h exit main ENDP aProc PROC USES eax ebx, x: DWORD, y: DWORD LOCAL a:DWORD, b:DWORD PARAMS = 2 LOCALS = 2 SAVED_REGS = 2 mov a,0AAAAh mov b,0BBBBh INVOKE WriteStackFrame, PARAMS, LOCALS, SAVED_REGS Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 25 Seção seguinte • • • • Stack Frames Recursão INVOKE, ADDR, PROC e PROTO MACROS Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 26 Recursão • O que é recursão? • Calcular recursivamente uma soma • Cálculo de um Fatorial Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 27 O que é recursão? • Um processo criado quando . . . • Um procedimento chama a si próprio • Procedimento A chama procedimento B, que por sua vez chama o procedimento A • Usando um grafo em que cada nó é um procedimento e cada aresta é uma chamada de procedimento, a recursão forma um ciclo: A E B D C Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 28 Calcular recursivamente uma soma O procedimento CalcSum calcula recursivamente a soma de um vetor de inteiros. Recebe: ECX = count. Retorna: EAX = sum CalcSum PROC cmp ecx,0 jz L2 add eax,ecx dec ecx call CalcSum L2: ret CalcSum ENDP ; ; ; ; ; check counter value quit if zero otherwise, add to sum decrement counter recursive call Stack frame: Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 29 Calculando um fatorial (1 de 3) Esta função calcula o fatorial do inteiro n. Um novo valor de n é salvo em cada stack frame: int function factorial(int n) { if(n == 0) return 1; else return n * factorial(n-1); } recursive calls backing up 5! = 5 * 4! 5 * 24 = 120 4! = 4 * 3! 4 * 6 = 24 3! = 3 * 2! 3*2=6 2! = 2 * 1! 2*1=2 1! = 1 * 0! 1*1=1 0! = 1 1=1 A cada retorno de uma chamada recursiva, o produto que retorna é multiplicado pelo valor prévio de n. (base case) Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 30 Calculando um fatorial Factorial PROC push ebp mov ebp,esp mov eax,[ebp+8] cmp eax,0 ja L1 mov eax,1 jmp L2 L1: dec eax push eax call Factorial ; ; ; ; (2 de 3) get n n < 0? yes: continue no: return 1 ; Factorial(n-1) ; Instructions from this point on execute when each ; recursive call returns. ReturnFact: mov ebx,[ebp+8] mul ebx ; get n ; eax = eax * ebx L2: pop ebp ret 4 Factorial ENDP ; return EAX ; clean up stack Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 31 Calculando um fatorial (3 de 3) 12 n ReturnMain Supondo o cálculo de 12! O diagrama mostra os primeiros stack frames criados por chamadas recursivas a Factorial Cada chamada recursiva usa 12 bytes do espaço de pilha. ebp0 11 n-1 ReturnFact ebp1 10 n-2 ReturnFact ebp2 9 n-3 ReturnFact ebp3 (etc...) Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 32 Seção seguinte • • • • Stack Frames Recursão INVOKE, ADDR, PROC e PROTO MACROS Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 33 INVOKE, ADDR, PROC e PROTO • • • • • • Diretiva INVOKE Operador ADDR Diretiva PROC Diretiva PROTO Classificação de Parâmetros Exemplo: troca de dois inteiros Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 34 Diretiva INVOKE • A diretiva INVOKE é uma poderosa substituição para a instrução CALL que permite a passagem de múltiplos argumentos • Sintaxe: INVOKE procedureName [, argumentList] • ArgumentList é uma lista opcional delimitada por vírgula de argumentos de procedimento • Argumentos podem ser: • Valores imediatos e expressões inteiras • Nomes de variáveis • Endereços e expressões ADDR • Nomes de registradores Web site Examples 35 Exemplos de INVOKE .data byteVal BYTE 10 wordVal WORD 1000h .code ; direct operands: INVOKE Sub1,byteVal,wordVal ; address of variable: INVOKE Sub2,ADDR byteVal ; register name, integer expression: INVOKE Sub3,eax,(10 * 20) ; address expression (indirect operand): INVOKE Sub4,[ebx] Web site Examples 36 Operador ADDR • Retorna um ponteiro de uma variável: • Exemplo: .data myWord WORD ? .code INVOKE mySub,ADDR myWord Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 37 Diretiva PROC (1 de 2) • A diretiva PROC declara um procedimento com uma lista opcional de parâmetros. • Sintaxe: label PROC paramList • paramList é uma lista de parâmetros separados por vírgulas. Cada parâmetro tem a seguinte sintaxe: paramName : type type deve ser um dos tipos padrões (BYTE, SBYTE, WORD, etc.), ou um ponteiro a um desses tipos. Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 38 Diretiva PROC (2 de 2) • Os formatos alternativos permitem lista de parâmetros serem em uma ou mais linhas separadas: label PROC, comma required paramList • Os parâmetros podem ser na mesma linha . . . param-1:type-1, param-2:type-2, . . ., param-n:type-n • Ou podem ser em linhas separadas: param-1:type-1, param-2:type-2, . . ., param-n:type-n Web site Examples 39 Procedimento AddTwo (1 de 2) • O procedimento AddTwo recebe dois inteiros e retorna a soma em EAX. AddTwo PROC, val1:DWORD, val2:DWORD mov eax,val1 add eax,val2 ret AddTwo ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 40 Exemplos de PROC (2 de 3) FillArray recebe um ponteiro a um vetor de bytes, um único byte que é copiado a cada elemento do vetor, e o tamanho do vetor. FillArray PROC, pArray:PTR BYTE, fillVal:BYTE arraySize:DWORD mov ecx,arraySize mov esi,pArray mov al,fillVal L1: mov [esi],al inc esi loop L1 ret FillArray ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 41 Exemplos de PROC (3 de 3) Swap PROC, pValX:PTR DWORD, pValY:PTR DWORD . . . Swap ENDP ReadFile PROC, pBuffer:PTR BYTE LOCAL fileHandle:DWORD . . . ReadFile ENDP Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 42 Diretiva PROTO • Cria um protótipo de procedimento • Sintaxe: • label PROTO paramList • Todo procedimento chamado pela diretiva INVOKE deve ter um protótipo • Uma definição de procedimento completa pode também servir como o próprio protótipo Web site Examples 43 Diretiva PROTO • Configuração padrão: PROTO aparece no topo da listagem do programa, INVOKE aparece no segmento de código, e a implementação do procedimento ocorre depois. MySub PROTO ; procedure prototype .code INVOKE MySub ; procedure call MySub PROC . . MySub ENDP ; procedure implementation Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 44 Exemplo de PROTO • Protótipo para o procedimento ArraySum , mostrando a sua lista de parâmetros: ArraySum PROTO, ptrArray:PTR DWORD, szArray:DWORD Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. ; points to the array ; array size Web site Examples 45 Seção seguinte • • • • Stack Frames Recursão INVOKE, ADDR, PROC e PROTO MACROS Web site Examples 46 Macros • • • • Introducing Macros Defining Macros Invoking Macros Macro Examples Web site Examples 47 Introducing Macros • A macro1 is a named block of assembly language statements. • Once defined, it can be invoked (called) one or more times. • During the assembler's preprocessing step, each macro call is expanded into a copy of the macro. • The expanded code is passed to the assembly step, where it is checked for correctness. 1Also called a macro procedure. Web site Examples 48 Defining Macros • A macro must be defined before it can be used. • Parameters are optional. • Each parameter follows the rules for identifiers. It is a string that is assigned a value when the macro is invoked. • Syntax: macroname MACRO [parameter-1, parameter2,...] statement-list ENDM Web site Examples 49 mNewLine Macro Example This is how you define and invoke a simple macro. mNewLine MACRO call Crlf ENDM .data .code mNewLine ; define the macro ; invoke the macro The assembler will substitute "call crlf" for "mNewLine". Web site Examples 50 mPutChar Macro Writes a single character to standard output. Definition: Invocation: Expansion: mPutchar MACRO char push eax mov al,char call WriteChar pop eax ENDM .code mPutchar 'A' 1 1 1 1 push eax mov al,'A' call WriteChar pop eax Web site viewed in the listing file Examples 51 Invoking Macros (1 of 2) • When you invoke a macro, each argument you pass matches a declared parameter. • Each parameter is replaced by its corresponding argument when the macro is expanded. • When a macro expands, it generates assembly language source code. • Arguments are treated as simple text by the preprocessor. Web site Examples 52 Invoking Macros (2 of 2) Relationships between macros, arguments, and parameters: macro invocation statement passes text consists of assembly code argument generates replaces parameter declared inside macro Web site Examples 53 mWriteStr Macro (1 of 2) Provides a convenient way to display a string, by passing the string name as an argument. mWriteStr MACRO buffer push edx mov edx,OFFSET buffer call WriteString pop edx ENDM .data str1 BYTE "Welcome!",0 .code mWriteStr str1 Web site Examples 54 mWriteStr Macro (2 of 2) The expanded code shows how the str1 argument replaced the parameter named buffer: mWriteStr push mov call pop ENDM MACRO buffer edx edx,OFFSET buffer WriteString edx 1 1 1 1 edx edx,OFFSET str1 WriteString edx push mov call pop Web site Examples 55 mReadStr The mReadStr macro provides a convenient wrapper around ReadString procedure calls. mReadStr MACRO varName push ecx push edx mov edx,OFFSET varName mov ecx,(SIZEOF varName) - 1 call ReadString pop edx pop ecx ENDM .data firstName BYTE 30 DUP(?) .code mReadStr firstName Web site Examples 56 mGotoXY The mGotoXY macro sets the console cursor position by calling the Gotoxy library procedure. mGotoxy push mov mov call pop ENDM MACRO X:REQ, Y:REQ edx dh,Y dl,X Gotoxy edx The REQ next to X and Y identifies them as required parameters. Web site Examples 57 mDumpMem The mDumpMem macro streamlines calls to the link library's DumpMem procedure. mDumpMem MACRO address, itemCount, componentSize push ebx push ecx push esi mov esi,address mov ecx,itemCount mov ebx,componentSize call DumpMem pop esi pop ecx pop ebx ENDM Web site Examples 58 mDump The mDump macro displays a variable, using its known attributes. If <useLabel> is nonblank, the name of the variable is displayed. mDump MACRO varName:REQ, useLabel IFB <varName> EXITM ENDIF call Crlf IFNB <useLabel> mWrite "Variable name: &varName" ELSE mWrite " " ENDIF mDumpMem OFFSET varName, LENGTHOF varName, TYPE varName ENDM Web site Examples 59 mWrite The mWrite macro writes a string literal to standard output. It is a good example of a macro that contains both code and data. mWrite MACRO text LOCAL string .data string BYTE text,0 .code push edx mov edx,OFFSET string call Writestring pop edx ENDM ;; data segment ;; define local string ;; code segment The LOCAL directive prevents string from becoming a global label. Web site Examples 60 The End Irvine, Kip R. Assembly Language for Intel-Based Computers 5/e, 2007. Web site Examples 61