CS2011, A Term 1999 Prof. Sergio A. Alvarez Solutions to the Practice Problems for Test 2 Name: ______________________ Login: _____________ Section: ____ Instructions: Read each problem carefully. Write your answers clearly. Include brief explanations for your solutions. Unexplained answers may not receive full credit. Each problem is worth 50 points. Good luck! 1) Assume that the two instructions PUSH BX, PUSH CX were executed (in that order) immediately before the following debug display was produced: AX=3520 BX=00FF CX=1234 DX=FFE2 SP=FF00 BP=0000 SI=0000 DI=0000 DS=1000 ES=0FF0 SS=12EB CS=1F76 IP=010A NV UP EI PL NZ NA PO NC 1F76:010A 58 POP AX a) Give the new contents of the CS, IP, SS, and SP registers immediately after the next instruction is executed. new CS = old CS = 1F76h new IP = old IP + length of current instruction = 010A + 1 = 010Bh new SS = old SS = 12EBh new SP = old SP + number of bytes in AX = FF00 + 2 = FF02h b) Draw a diagram that shows how the top of the stack changes as a result of executing the next instruction. Give explicit segment:offset addresses and hex contents for each memory location involved. Include both the old and new stack tops in your diagram. address ------------- 12EB:FF03 00h ------------- 12EB:FF02 FFh <-- new SP (stack top pointer) ------------- 12EB:FF01 12h ------------- 12EB:FF00 34h <-- old SP (stack top pointer) ------------- 2) Assume that the initial register contents are exactly as given above in problem 1), except that the instruction about to be executed is now: 1F76:010A 082300 CALL 0130 a) Give the new contents of the CS, IP, SS, and SP registers immediately after the next instruction is executed. new CS = old CS = 1F76h new IP = 0130h new SS = old SS = 12EBh new SP = old SP - number of bytes in IP = FF00 - 2 = FEFEh b) Draw a diagram that shows how the top of the stack changes as a result of executing the next instruction. Give explicit segment:offset addresses and hex contents for each memory location involved. Include both the old and new stack tops in your diagram. address ------------- 12EB:FF01 12h ------------- 12EB:FF00 34h <-- old SP (stack top pointer) ------------- 12EB:FEEF 01h ------------- 12EB:FEFE 0Dh <-- new SP (stack top pointer) ------------- 3) Consider the following assembly language instructions: mov ax,0103h mov dx,0 mov bx,0020h div bx a) State what registers the dividend (numerator), divisor (denominator), quotient, and remainder will be taken from or placed in (in connection with the div bx instruction shown). dividend in DX:AX divisor in BX quotient in AX remainder in DX b) Give the final hex contents of registers AX, BX, DX after the above sequence of instructions has been executed. 0103h/0020h = (0100h + 3h) / 20h = 8h, remainder 3h => after div bx: ax contains 0008h, bx contains 0020h, dx contains 0003h 4) Fill in the steps below to write an 80X86 assembly language procedure named twopower that accepts a singleword unsigned integer n as input on the stack and recursively calculates the n-th power of 2, returning the result in register AX (assume that the result occupies no more than 16 bits). Your answer to part (a) should be in high-level functional notation like twopower(n) = twopower(n-5). Your answers to parts (b)-(e) should be in 80X86 assembly language. a) Let twopower(n) denote the n-th power of 2. Give a recursive definition of twopower(n), in terms of a recursive relation together with a suitable base case. base case: twopower(0) = 1 (also acceptable: twopower(1) = 2) recursive case: twopower(n) = twopower(n-1)*2 if n > 0. b) Define the start of a procedure named twopower, set up a stack frame in the usual way, and retrieve the parameter n from the stack, placing it in register BX. twopower proc ; set up stack frame push bp mov bp,sp ; retrieve argument, place in bx push bx mov bx,[bp+4] c) Check for the base case, jump to a label called recurse if the base case does not occur, and handle the base case otherwise, jumping to a label called cleanup at the end. ; check for base case cmp bx,0 jnz recurse ; handle base case mov ax,1 jmp cleanup d) Starting with the label recurse, handle the recursive case, calling twopower with the appropriate arguments, and leaving the desired final result in register AX. ; handle recursive case recurse: dec bx push bx call twopower mov bx,2 mul bx e) Starting with the label cleanup, finalize the stack frame and return, clearing the stack as appropriate. ; finalize stack frame, return and clear stack cleanup: pop bx pop bp ret 2 twopower endp 5) Given the data allocation: .data bitbunch dw 0010h number dw 000Ah Consider the following assembly language loop intended to accumulate in AX the product of (the low bytes of) bitbunch and number using the shift-and-add method described in class. sumloop: bt bitbunch,dx jnc L add ax,number L: shl number,1 inc dx loop sumloop a) State explicitly what the initial value should be for each of the registers AX, CX, DX immediately before executing the above loop so that the loop correctly computes the desired product in AX. In each case briefly explain why. AX = 0 because the accumulated sum should start at 0 CX = 8 because CX is the loop counter and 8 bits/shifts are needed DX = 0 because DX is the index of the tested bit which is incremented on each pass and which should cover the range 0..7 b) Give the correct final values for each of the registers AX, CX, DX immediately after the above loop has finished executing. AX = 00A0h, the product of 10h and 0Ah CX = 0, the exit value for the loop counter DX = 8, because DX starts at 0 and has been incremented 8 times 6) a) Give the absolute addresses of the memory locations in which the interrupt vector for INT 10h is stored. Specify how many memory locations are needed. Four memory locations (bytes) are needed. The corresponding absolute addresses are 00040h, 00041h, 00042h, 00043h. (The first address is obtained by multiplying the interrupt number by four) b) Describe the sequence of events involved in handling software interrupt INT 21h. Be explicit about memory locations, control branching, and the like. The sequence of events is similar to that for a far call, except that the Flags register is pushed onto the stack before the return address is pushed at the start of the process, and, accordingly, at the end of the process the Flags register is popped from the stack after execution has resumed at the return address. Here is the sequence of events: The Flags register is pushed onto the stack. The contents of memory locations 00086h and 00087h are loaded into the CS register; the contents of memory locations 00084h and 00085h are loaded into the IP register; control branches to the new CS:IP address, where the interrupt handling procedure is located. The interrupt handling procedure eventually executes an IRET (return from interrupt) instruction, which pops the stack top into the IP register and then the new stack top into the CS register, and finally does another pop into the Flags register. Execution then resumes at the first instruction in the calling procedure following the INT 21h instruction. 7) Assume the following data allocation and assume that the variables defined here retain their initial values. .data buffer db 16 dup(' ') xtable db "0123456789ABCDEF" Write an assembly language procedure getascii that returns in AL the ASCII code of the hex symbol (0..9,A..F) corresponding to the number (0..15d) stored in DL. Use either the XLAT instruction or indirect addressing to extract the ASCII code from xtable. All registers except AX, IP, and the Flags register should be left unchanged by a call to your procedure. getascii proc push bx mov bx,offset xtable xor ax,ax mov al,dl xlat pop bx ret getascii endp A second alternative: getascii2 proc push dx push di xor ax,ax and dx,00ffh mov di,dx mov al,xtable[di] pop di pop dx ret getascii2 endp