7- Indirect Addressing, MASM Procedures, and System Stack Flashcards

1
Q

What is indirect addressing?

A

Using a register as a pointer and then manipulating the register’s value.

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

How can you do indirect addressing?

A

You can use any 32-bit general purpose register (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP). Since ESI contains the offset of byteVal, you can move al to byteVal’s memory location.

.data
byteVal BYTE 10h
.code
mov esi, OFFSET byteVal
mov al, [esi]      ;AL = 10h
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What happens if the destination operand uses indirect addressing?

A

Then whatever is from the source will be copied to the destination. For example, this will copy whatever’s in BL into whatever address is stored in esi.

mov [esi], bl

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

How can you use indirect operands for stepping through arrays?

A

You simply point to the address and then add the size of each element to esi.

.data
arrayW WORD 1000h, 2000h, 3000h
.code
mov esi, OFFSET arrayW
mov ax, [esi]      ;AX = 1000h
add esi, 2
mov ax, [esi]       ;AX = 2000h
add esi, 2
mov ax, [esi]       ;AX = 3000h
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What are indexed operands and how do you use them?

A

constant[reg]
[constant + reg]

An indexed operand adds a constant to any of the 32-bit registers to generate an effective address.They are great for array processing as long as the index register is initialized to zero.

.data
arrayB BYTE 10h, 20h, 30h
.code
mov esi, 0
mov al, arrayB[esi]       ;AL = 10h
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

How do you add displacements to indexed operands?

A

You just add the size of the element to the register within the indexed operand.

.data
arrayW WORD 1000h, 2000h, 3000h
.code
mov esi, OFFSET arrayW
mov ax, [esi]            ;AX = 1000h
mov ax, [esi+2]        ;AX = 2000h
mov ax, [esi+4]        ;AX = 3000h
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Can you use 16-bit registers as indexed operands?

A

In real-address mode, it is usual to do so (in protected, you use 32-bit ones). However, that means you are limited to using SI, DI, BX, or BP (try to only use BP when addressing data on the stack)

mov al, arrayB[si]
mov ax, arrayW[di]
mov eax, arrayD[bx]

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

How is TYPE used to compensate for element sizes in indexed operands?

A

You can multiply the subscript the size of the element using TYPE.

.data
arrayD DWORD 100h, 200h, 300h, 400h
mov esi, 3 * TYPE arrayD ;offset of arrayD[3]
mov eax, arrayD[esi] ;EAX = 400h

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

What is a scale factor and how is it used?

A

Instead of using TYPE, Intel designers wanted to just allow direct scale factors for each element (word = 2, doubleword = 4, quadword = 8).

.data
arrayD  DWORD 1, 2, 3, 4
,code
mov esi, 3                   ;subscript
mov eax,arrayD[esi*4]    ;EAX =4
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

How do you use pointers in MASM?

A

You can either just say “variable type variable “ or make it more clear by saying “variable type OFFSET variable”.

.data
arrayB byte 10h, 20h, 30h, 40h
ptrB dword arrayB

OR

ptrB dword OFFSET arrayB

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

How do you use the TYPEDEF operator?

A

It lets you create a user-defined type that has all the status of a built-in type when defining variables. It is ideal for creating pointer variables (this creates a new data type PBYTE that is a pointer to bytes).

PBYTE TYPEDEF PTR BYTE

.data
arrayB BYTE 10h, 20h, 30h, 40h
ptr1 PBYTE ? ;uninitialized
ptr2 PBYTE arrayB ;points to an array

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

What is an example of a TYPEDEF usage?

A

PBYTE TYPEDEF PTR BYTE

.data
arrayB BYTE 10h, 20h, 30h
ptr1 BYTE arrayB

.code
main PROC
mov esi, ptr1
mov al, [esi]     ;10h
invoke ExitProcess, 0
main ENDP
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Can any 32-bit general purpose register be used as an indirect operand?

A

Yes.

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

Is the EBX register usually reserved for addressing the stack?

A

No, it’s the ESP register.

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

Is the following instruction valid?

inc [esi]

A

No, you’d have to just say inc esi.

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

Is the following an indexed operand?

array[esi]

A

Yes, just the first element in the array (as long as esi were 0)

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

What are subroutines called in C/C++ and MASM?

What are the values passed to a subroutine called?

A

In C/C++, they’re called functions. In MASM, they’re called procedures.

The values passed to them are called arguments, and when the values are received by the subroutine, they’re called parameters.

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

What type of parameters do subroutines receive on the runtime stack in 32-bit mode?

A

In 32-bit mode, stack parameters are always used (as opposed to the register parameters we’ve been using).

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

What is the stack frame (or activation record)?

A

The area of the stack set aside for passed arguments, subroutine return address, local variables, and saved registers.

20
Q

How is the stack frame created?

A
  1. Passed arguments, if any, are pushed onto the stack
  2. The subroutine is called, causing the subroutine return address to be pushed onto the stack.
  3. As the subroutine begins to execute, EBP is pushed on the stack.
  4. EBP is set equal to ESP. From this point on, EBP acts as a base reference for all of the subroutine parameters.
  5. If there are local variables, ESP is decremented to reserve space for the variables on the stack.
  6. If any registers need to be saved, they are pushed on the stack.
21
Q

What were the disadvantages of register parameters?

A

For years, Microsoft included a parameter passing convention named fastcall (efficiency by placing parameters in registers). However, these ALSO are used to hold data values such as loop counters and operands in calculations.

Therefore, any registers used as parameters must be pushed on the stack before procedure calls, assigned the values of procedure arguments, and later restored to their original values after the procedure returns. This ends up being SLOWER and requires being careful that each register’s PUSH is matched by the appropriate POP.

22
Q

How do stack parameters fix this problem?

A

Just before a subroutine call, the arguments are pushed onto the stack (either value arguments or reference arguments). For example, if DumpMem used stack parameters, we would call it using the following code.

push TYPE array
push LENGTHOF array
push OFFSET array
call DumpMem

23
Q

How can you pass by value?

A

A copy of the value is pushed onto the stack.

.data
val1  DWORD 5
val2 DWORD 6
.code
push val2
push val1
call AddTwo

The stack would look like this:

(val2) - 6
(val1) - 5

24
Q

How can you pass by reference?

A

An argument passed by reference consists of the address of an object. The following arguments call Swap, passing the two arguments by reference:

push OFFSET val2
push OFFSET val1
call Swap

offset(val2)
offset(val1)

25
Q

How can you pass arrays?

A

You can just pass the address of the array. For example, this will pass the offset of an array to a subroutine named ArrayFill

.data
array DWORD 50 DUP(?)
.code
push OFFSET array
call ArrayFill
26
Q

How do high-level languages like C/C++ initialize and access parameters during function calls?

A

They begin with a prologue consisting of statements that save the EBP register and point EBP to the top of the stack. (OR, they push certain registers on the stack whose values will be restored when the function returns).

The end of the function is an epilogue in which the EBP register is restored and RET instruction returns to the caller.

27
Q

What would this AddTwo function in C look like in assembly language?

int AddTwo(int x, int y)
{
     return x + y;
}
A

In the prologue, AddTwo pushes EBP on the stack to preserve its value. Then, EBP is set to ESP so that ESP can be the base pointer for the stack frame.

AddTwo PROC
push ebp
mov ebp, esp

If you did AddTwo(5, 6), then the stack would look like:
6 -- [EBP+12]
5 -- [EBP+8]
return address --{EBP+4]
EBP
28
Q

What are explicit stack parameters?

A

When stack parameters are referenced with expressions like [ebp+8]. Some programmers define symbolic constants to represent the explicit stack parameters to make their code easier to read:

y_param EQU [ebp + 12]
x_param EQU [ebp + 8]

AddTwo PROC
   push ebp
   mov  ebp, esp
   mov, eax, y_param
   add, eax, x_param
   pop ebp
   ret
AddTwo ENDP
29
Q

Why is it necessary to clean the runtime stack?

A

Otherwise, you would at least have a memory leak and at worst have a corrupted stack. For example, the AddTwo procedure might leave this on the stack:

return address
6
5

30
Q

What are the two major 32-bit calling conventions?

A

The C calling convention and the STDCALL calling convention. Both are used on Windows, and both help to clear the stack.

31
Q

What is the C calling convention?

A

Subroutine parameters are pushed on the stack in reverse order. Then, when a program calls a subroutine, it follows the CALL instruction with a statement that adds a value to the ESP equal to the combined sizes of the subroutine parameters.

Example1 PROC
  push 6
  push 5
  call AddTwo
  add esp, 8
  ret
Example1 ENDP
32
Q

What is the STDCALL Calling Convention?

A

Like C, it pushes arguments on the stack in reverse order. It also supplies an integer parameter to the RET instruction, which adds 8 to ESP after returning to the calling procedure. It must equal the number of bytes of stack space consumed by the procedure’s parameters.

AddTwo PROC
  push ebp
  mov ebp, esp
  mov eax, [ebp + 12]
  add eax, [ebp + 8]
  pop ebp
  ret 8
AddTwo ENDP

Therefore, programs always remove arguments from the stack in the calling program AFTER a subroutine has returned.

33
Q

What are some major differences between the C calling convention and the STDCALL calling convention?

A

By having a parameter in the RET instruction, STDCALL reduces the amount of code for subroutine calls and ensures that they never forget to clean up the stack.

On the other hand, the C calling convention permits subroutines to declare a variable number of parameters. The caller can decide how many arguments it will pass.

For example, the printf function number of arguments depend on the number of format specifiers (e.g. %d). The function implementation has no convenient way of encoding a constant in the RET instruction to clean up the stack, so it’s up to the caller.

34
Q

Why do you save and restore registers?

A

Subroutines often save the current contents of registers on the stack before modifying them because they can restore the original values just before the subroutine returns.

35
Q

How do you save and restore registers?

A

Assume that mySub procedure has one stack parameter. It pushes ECX and EDX after setting EBP to the base of the stack frame and loads the stack parameter into EAX.

MySub PROC
  push ebp   ;save base pointer
  mov ebx, esp   ;base of stack frame
  push ecx
  push edx
  mov eax, [ebp + 8]   ;get the stack parameter
  . .
  pop edx     ;restore saved registers
  pop ecx     ;restore base pointer
  pop ebp     ;clean up the stack
  ret
MySub ENDP

After it’s initialized, EBP’s contents are fixed. Pushing ECX and EDX don’t affect displacement from EBP because the stack grows below EBP.

(parameter) [EBP +8]
return address [EBP + 4]
EBP

36
Q

How are local variables created?

A

They are created on the runtime stack, usually below the base pointer (EBP). For example, the following function would allocate local variables:

void MySub()
{
   int x = 10;
   int y = 20;
}

x would be EBP - 4
y would be EBP - 8

37
Q

How does would the C calling convention create the local variables in this program?

void MySub()
{
   int x = 10;
   int y = 20;
}
A
MySub PROC
   push ebp
   mov ebp, esp
   sub esp, 8     ;create locals
   mov DWORD PTR [ebp-4], 10  ;x
   mov DWORD PTR [ebp-8], 20    ;y
  mov esp, ebp    ;remove locals from the stack
  pop ebp
  ret
MySub ENDP 

WATCH OUT!! If you don’t include the mov esp, ebp (resetting the stack pointer by assigning it the value of EBP), then RET will return to an invalid address!!

38
Q

How are reference parameters usually accessed?

A

By procedures using base-offset addressing from EBP. If a pointer to an array is located at stack address [ebp+12], statement will copy the pointer into ESI:

mov esi, [ebp+12] ;points to the array.

39
Q

What is an input parameter?

A

An input parameter is data passed by a calling program to a procedure.

The called procedure is NOT expected to modify the corresponding argument variable, and even if it does, the modification is confined to the procedure.

40
Q

What is an output parameter?

A

An output parameter is created by passing the address of an argument variable when a procedure is called.

The “address of” a variable is the same as OFFSET. The value is NOT used in th calculation in the procedure.

41
Q

What is an input-output parameter?

A

The address of an argument variable that contains input that will both be USED AND MODIFIED by the procedure.

42
Q

What are the methods of passing among procedures?

A
  1. Use shared memory (global variables)
  2. Pass parameters in registers
  3. Pass parameters on the system stack
43
Q

What’s good and bad about global variables?

A

Generally, it’s BAD because the procedure might change memory contents needed by other procedures!! There’s NO clear interface between any two procedures.

44
Q

What’s good/bad about passing through registers?

A

Generally, it’s BAD again because the procedure might change register contents!!

However, some Irvine library procedures require values in registers (b/c these are easier).

45
Q

What’s good/bad about passing parameters on the system stack?

A

The calling procedure is required to push these onto the stack before the call, but the call places the return addresses on the top of the stack, making it inaccessible. So, you have to remove the parameters and return to the calling program.

However, it’s much more efficient because you don’t have to save and then renew the previous values.

On the other hand, some “setup” is involved in the calling procedure and some “bookkeeping” is involved in the called procedure.