7- Indirect Addressing, MASM Procedures, and System Stack Flashcards
What is indirect addressing?
Using a register as a pointer and then manipulating the register’s value.
How can you do indirect addressing?
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
What happens if the destination operand uses indirect addressing?
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 can you use indirect operands for stepping through arrays?
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
What are indexed operands and how do you use them?
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 do you add displacements to indexed operands?
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
Can you use 16-bit registers as indexed operands?
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 is TYPE used to compensate for element sizes in indexed operands?
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
What is a scale factor and how is it used?
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 do you use pointers in MASM?
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 do you use the TYPEDEF operator?
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
What is an example of a TYPEDEF usage?
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
Can any 32-bit general purpose register be used as an indirect operand?
Yes.
Is the EBX register usually reserved for addressing the stack?
No, it’s the ESP register.
Is the following instruction valid?
inc [esi]
No, you’d have to just say inc esi.
Is the following an indexed operand?
array[esi]
Yes, just the first element in the array (as long as esi were 0)
What are subroutines called in C/C++ and MASM?
What are the values passed to a subroutine called?
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.
What type of parameters do subroutines receive on the runtime stack in 32-bit mode?
In 32-bit mode, stack parameters are always used (as opposed to the register parameters we’ve been using).
What is the stack frame (or activation record)?
The area of the stack set aside for passed arguments, subroutine return address, local variables, and saved registers.
How is the stack frame created?
- Passed arguments, if any, are pushed onto the stack
- The subroutine is called, causing the subroutine return address to be pushed onto the stack.
- As the subroutine begins to execute, EBP is pushed on the stack.
- EBP is set equal to ESP. From this point on, EBP acts as a base reference for all of the subroutine parameters.
- If there are local variables, ESP is decremented to reserve space for the variables on the stack.
- If any registers need to be saved, they are pushed on the stack.
What were the disadvantages of register parameters?
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.
How do stack parameters fix this problem?
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
How can you pass by value?
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
How can you pass by reference?
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)