5 - Procedures Flashcards

1
Q

What is the runtime stack?

A

A memory array managed directly by the CPU, using the ESP (extended stack pointer) register. We rarely manipulate ESP directly - usually we used instructions like CALL, RET, PUSH, and POP.

ESP always points to the last value to be added to, or pushed on, the top of the stack. (e.g. if ESP = 00001000h, then the address 0001000 holds the only value of the stack.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

How does a push operation work?

A

PUSH reg/mem16 (-2 ESP)
PUSH reg/mem32 (-4 ESP)
PUSH imm32

It decrements the stack pointer and places the next value at the next lowest address.

00001000 - 00000006 - ESP
00000FFC
00000FF8

00001000 - 00000006
00000FFC - 000000A5 - ESP
00000FF8

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How does a pop operation work?

A

POP reg/mem16
POP reg/mem32

It removes a value from the stack, increments the ESP, and removes the last value.

00001000 - 00000006
00000FFC - 000000A5 - ESP
00000FF8 - 00000001 - ESP
00000FF0

00001000 - 00000006
00000FFC - 000000A5 - ESP
00000FF8

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What are the uses of runtime stacks in programs?

A
  1. A temporary save area for registers when they are used for more than one purpose. After they are modified, they can be restored.
  2. When the CALL instruction executes, the CPU saves the current subroutine’s return address on the stack.
  3. When calling a subroutine, you pass input values called arguments by pushing them on the stack.
  4. The stack provides temporary storage for local variables inside subroutines.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What do the PUSHFD and POPFD instructions do?

A

PUSHFD pushes the EFLAGS register onto the stack, and POPFD pops the stack into EFLAGS.

You use these because the MOV instruction cannot be used to copy the flags to a variable. Therefore, you can just use this to save to a variable:
pushfd
pop saveflags

And use this to restore from the same variable
push saveFlags
popfd

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How can you use the PUSHAD /POPAD or PUSHA/POPA instructions?

A

PUSHAD pushes all the 32-bit general purpose registers onto the stack in this order (EAX, ECX, EDX, EBX, ESP (value before), EBP, ESI, and EDI). POPAD pops them off in reverse order.

PUSHA and POPA are the same for 16-bit registers (AX, CX, DX, BX, SP, BP, SI, DI).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

When do you use PUSHAD and POPAD?

A

Generally, if you write a procedure that modifies a number of 32-bit registers, use PUSHAD at the beginning of the procedure and POPAD at the end to save and restore the registers.

pushad ; save general-purpose registers
.
.mov eax, ....
mov edx, ...
mov ecx, ...
. 
popad ; restore general-purpose registers
ret
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

When do you not want to use PUSHAD and POPAD?

A

When you actually care about the results after you PUSHAD. For example, if you put a return value into EAX, you don’t want that instruction the middle of pushad and popad, which will overwrite it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

How can you reverse a a string using the stack?

A

Put the size of the name in ECX, put each character (using ESI=0 as your index) into a register and push that onto the stack, increment ESI, and loop back until it’s a null character.

mov ecx, nameSize
mov esi, 0
L1: movzx eax, aName[esi]
push eax
inc esi
loop L1

Then, you can put the size of the name in ECX (using ESI=0 as your index), pop eax to get the character, and mov everything from al into the same character array, incrementing ESI each time.

mov ecx, nameSize
mov esi, 0
L2: pop eax
mov aName[esi], al
inc esi
loop L2
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Which register manages the stack?

A

ESP

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

When a 32-bit value is pushed on the stack, what happens to ESP?

A

ESP is decremented by 4.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

It is true or false that local variables in procedures are created on the stack?

A

True.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Is it true or false that the PUSH instruction cannot have an immediate operand?

A

False - you can definitely push just a value.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is a procedure?

A

Generally, it’s a subroutine (in higher-level languages, they’re just methods or functions).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How do you define a procedure?

A

You use the PROC and ENDP directives. Whenever you create a procedure other than your program’s startup procedure, you MUST end it with the RET instruction, which forces the CPU to return to the location where the procedure was.

sample PROC

ret
sample ENDP

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What are labels in procedure?

A

By default, labels are visible only within the procedure in which they are declared. WATCH OUT! This can be a problem when you have jmp and loop instructions (the label after JMP MUST be located in the same procedure as the JMP instruction).

You can work around this limitation by declaring a global label, with (::) after its name
(e.g. Destination::). However, it’s not a good idea to jump or loop outside the current procedure because the runtime stack may become corrupted.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

How can you create a PROC that calculates the sum of three 32-bit integers?

A

The following code returns the sum of EAX, EBX, and ECX in EAX.

SumOf PROC
  add eax, ebx
  add eax, ecx
  ret
SumOf ENDP
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What kind of comments should you put at the beginning of each procedure?

A

A description of all tasks accomplished, a list of input parameters and their uses (e.g. Receives…), description of any values returned (e.g. Returns…), and any preconditions (e.g. Requires…).

;———————————–
; sumof
;
; Calculates and returns the sum of 32-bit integers.
; Receives: EAX, EBX, ECX, the three integers. May be signed or unsigned.
; Returns: EAX = sum
———————————–

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

How are the CALL and RET instructions used?

A

The CALL instruction calls a procedure by directing the processor to begin execution at a new memory location. The procedure uses a RET (return from procedure) instruction to bring the processor back to the point in the program where the procedure was called.

The CALL instruction pushes its return address on the stack and copies the called procedure’s address into the instruction pointer. When the procedure is ready to return, the RET instruction pops the return address from the stack into the instruction pointer. In 32-bit mode, the CPU executes the instruction in memory pointed to by EIP.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

What happens to the stack, EIP, and ESP in the following instructions (at the following offsets)?

main PROC
00000020 - call MySub
00000025 - mov eax, ebx

MySub PROC
00000040 - mov eax, edx
....
ret
MySub ENDP
A

When the CALL instruction executes, the address following the call (00000025) is pushed onto the stack and the address of MySub is loaded into EIP. All instructions in MySub execute up to its RET instruction.

When the RET instruction executes, the value in the stack pointed to by ESP is popped into EIP. Then, ESP is incremented so it points to the previous value on the stack.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

How can you make nested procedure calls?

A

Main calls a procedure named sub1, which calls procedure sub2.

When the RET instruction at the end of sub2 is about to execute, the stack looks like:
(ret to main)
(ret to sub1) - ESP

When sub1 returns, stack[ESP] is popped into the instruction pointer, and execution resumes in main.
(ret to main) - ESP

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

How can you pass register arguments to procedures?

A

Instead of having instructions for specific arrays, you can always create a procedure that receives a pointer to that array and returns a value.

For example, ArraySum will calculate the sum of an array of 32-bit integers, receiving ESI = the array offset, ECX = number of elements in the array, and returns EAX = sum of array elements.

ArraySum PROC
 push esi ;save ESI, ECX
 push ecx
 mov eax, 0 ;set the sum to zero
L1: add eax, [esi] ; add each integer to sum
 add esi, TYPE DWORD ;point to next integer
 loop L1 ; repeat for array size
pop ecx
pop esi
ret
ArraySum ENDP
23
Q

How can you use the USES operator?

A

It lets you list the names of all registers modified within a procedure by (1) generating PUSH instructions that save the registers on the stack at the beginning of the procedure and (2) generating POP instructions that store the register values at the end of the procedure.

For example, the ArraySum procedure could be:

ArraySum PROC USES esi, ecx
 move eax, 0
L1:
 add eax, [esi] ; add each integer to sum
 add esi, TYPE DWORD ; point to next integer
 loop L1 ; repeat for array size
 ret ; sum is in EAX
ArraySum ENDP
24
Q

When should the return register NOT be pushed and popped?

A

When a procedure returns a value in a register (usually EAX). For example, in the following example, the procedure return value is lost:

SumOf PROC
 push eax ;save EAX
 add eax, ebx ; calculate sum
 add eax, ecx ;calculate sum
 pop eax ;of EAX, EBX, ECX
 ret
SumOf ENDP
25
Q

Is is true or false that the PROC directive begins a procedure and the ENDP directive ends a procedure?

A

True - all procedures start with PROC and end with ENDP.

26
Q

Is it possible to define a procedure inside an existing procedure?

A

No. You can make nested procedures by simply calling another procedure inside a procedure. The older procedure will get pushed on the stack while the new one is being executed.

27
Q

What would happen if the RET instruction were omitted from a procedure?

A

TERRIBLE THINGS! Execution would continue BEYOND the end of the procedure, possibly into the beginning of another procedure.

This programming bug is VERY difficult to detect!

28
Q

Is it true that the CALL instruction pushes the offset of the CALL instruction on the stack?

A

No. It pushes the offset of the instruction FOLLOWING the call.

29
Q

What is a link library?

A

A file containing procedures (subroutines) that have been assembled into machine code. A link library begins one or more source files, which are assembled into object codes. The object files are inserted into a specially formatted filed recognized by the linker utility.

30
Q

Is is true or false that a link library consists of assembly language source code?

A

False. It contains object code.

31
Q

How would you use the PROTO directive to declare a procedure named MyPROC in an external link library?

A

MyProc PROTO

32
Q

Write a CALL statement that calls a procedure named MyProc in an external link library.

A

call MyProc

33
Q

What is the name of the 32-bit link library supplied with this book?

A

Irvine32.lib

34
Q

What type of file is kernel32.dll?

A

A dynamic link library that is a fundamental part of the MS-Windows operating system.

35
Q

What is a file handle?

A

A 32-bit integer used by Windows OS to identify a file that is currently open. When your program calls a Windows service to open or create a file, the OS creates a new file handle and makes it available to your program.

Each time you call an OS service method to read from or write to the file, you must pass the same file handle as a parameter to the service method.

36
Q

What happens if your programs calls procedures in the Irvine32 library and does not push 32-bit values onto the runtime stack?

A

The Win32 console functions will not work correctly!

ONLY push 32-bit values onto the runtime stack.

37
Q

How do you use the CloseFile procedure?

A

It closes a file that was created or opened. It is identified by a 32-bit integer handle passed in EAX. If the file is successfully closed, the value in EAX is nonzero.

mov eax, fileHandle
call CloseFile

38
Q

How do you use the Clrscr procedure?

A

It clears the console windows (usually called at the beginning and end of a program). Otherwise, use WaitMsg (to allow the user to view information on the screen before it is erased):

call WaitMsg ; “Press any key..”
call Clrscr

39
Q

How do you use the CreateOutputFile procedure?

A

It creates a new disk file and opens it for writing. When you call the procedure, place the offset of a filename in EDX. When the procedure returns, EAX will contain a valid file handle (32-bit integer) if the file was created successfully. Otherwise, EAX equals INVALID_HANDLE_VALUE.

.data
filename BYTE "newfile.txt",0
.code
mov edx, OFFSET filename
call CreateOutputFile
40
Q

How do you use the Delay procedure?

A

It pauses the program for a specified number of milliseconds. Before calling Delay, set EAX to the desired interval.

mov eax, 1000 ; 1 second
call Delay

41
Q

How do you use the DumpMem procedure?

A

It writes a range of memory to the console window in hexadecimal. Pass it the starting address in ESI, the number of units in ECX, and the unit size in EBX (1 = byte, 2 = word, 4 = doubleword).

This displays an array of 11 doublewords in hexadecimal:

.data
array DWORD 1, 2, 3, 4, 5, 6, 7, 8, 9, 0Ah, 0Bh
.code
main PROC
 mov esi, OFFSET array ;starting OFFSET
 mov ecx, LENGTHOF array ;number of units
mov ebx, TYPE array ;doubleword format
 call DumpMem
42
Q

How do you use the DumpRegs procedure?

A

It displays the EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP, EIP, and EFL (EFLAGS) registers in hexadecimal. It also displays the 6 flags.

43
Q

How do you use the GetCommandTail procedure?

A

It copies the program’s command line into a null-terminated string. If the command line was empty, the Carry flat is set. Otherwise, the Carry flag is cleared.

For example, you can use this to pass two txt files that you want to encrypt.

44
Q

How do you use the GetMaxXY procedure?

A

GetMaxXY procedure gets the size of the console window’s buffer (if it’s larger than the visible window size, scroll bars appear). It has no input parameters, but when it returns, DX has the number of columns and AX has the number of buffer rows. The possible range can be no larger than 255.

.data
rows BYTE ?
cols BYTE ?
.code
call GetMaxXY
mov rows, al
mov cols, dl
45
Q

How do you use the GetMSeconds?

A

The GetMseconds gets the number of milliseconds since midnight on the host computer, and returns a value in the EAX register. The procedure is a great tool for measuring the time between events (subtract the two time values).

.data
startTime DWORD ?
.code
call GetMseconds
mov startTime, eax
L1:
 ;(loop body)
 loop L1
call GetMSeconds
sub eax, startTime
46
Q

How do you use the GetTextColor procedure?

A

GetTextColor gets the current foreground and background of the console window. It returns the background color in the upper four bits of AL and the foreground color in the lower four bits.

.data
color byte ?
.code
call GetTextColor
mov color, AL
47
Q

How do you use Gotoxy procedure?

A

The Gotoxy procedure locates the cursor at a given row and column in the console window. By default, its X-coordinate is 0-79 and Y is 0-24. When you call Gotoxy, pass Y-coordinate(row) in DH and X-coordinate(column) in DL.

mov dh, 10
mov dl, 20
call Gotoxy

If the user has resized the console window, you can call GetMaxXY to find the current number of rows and columns.

48
Q

How do you use the IsDigit procedure?

A

It determines whether a value in AL is the ASCII code for a valid decimal digit. When calling it, pass an ASCII character in AL. The procedure sets the Zero flag if AL contains a valid decimal digits; otherwise it clears Zero flag.

mov AL, somechar
call IsDigit

49
Q

How do you use the MsgBox procedure?

A

It displays a graphical popup message box with an optional caption. Pass it the offset of a string in EDX, which will appear inside the box. Optionally, pass the offset of a string for box’s title in EBX. To leave the title blank, set EBX to zero.

.data
caption BYTE "Dialog Title", 0
HelloMsg BYTE "This is a popup.", 0dh, 0ah
.code
mov ebx, OFFSET caption
mov edx, OFFSET HelloMsg
call MsgBox
50
Q

How do you use the MsgBoxAsk procedure?

A

MsgBoxAsk displays a popup message with YES and NO buttons. Pass it the offset of a question string in EDX, which will appear inside the box. Optionally, pass the offset of a string for the box’s title in EBX (or set it to 0 to leave it blank). MsBoxAsk returns an integer in EAX that tells you which button was selected by the user. The value will be one of two predefined Windows constants (IDYES = 6 or IDNO = 7).

51
Q

How does the OpenInputFile procedure work?

A

It opens an existing file or input. Pass it the offset of a filename in EDX. When it returns, if the file was opened successfully, EAX will contain a valid file handle. Otherwise, EAX will equal INVALID_HANDLE_VALUE.

.data
filename BYTE "myfile.txt",0
.code
mov edx, OFFSET filename
call OpenInputFile
52
Q

How does the ParseDecimal32 procedure work?

A

It converts an unsigned decimal integer string to 32-bit binary. All valid digits are converted, and leading spaces are ignored. Pass it the offset of a string in EDX and string’s length in ECX. The binary value is returned in EAX.

.data
buffer BYTE "8193"
bufSize = ($ - buffer)
.code
mov edx, OFFSET buffer
mov ecx, bufSize
call ParseDecimal32

If the integer is blank, or if the integer contains only spaces, or if the integer is larger than 2^32-1, then EAX = 0, and CF = 1. Otherwise, EAX contains the converted integer and CF = 0.

53
Q

How does a ParseInteger32 procedure work?

A

It converts a signed decimal integer string to 32-bit binary. All valid digits from the beginning of the string to the first nonnumeric character are converted. Leading spaces are converted. Pass it to the offset of a string in EDX and the string’s length in ECX. The binary value is returned in EAX.

.data
buffer size "-8193"
bufSize = ($-buffer)
.code
mov edx, OFFSET buffer
mov ecx, bufSize
call ParseInteger32

If the value cannot be represented as a 32-bit integer, the overflow flag is set.