4 - Data Transfers, Add/Subract, JMP/LOOPS Flashcards
How can instructions have zero, one, two, or three operands?
mnemonic
mnemonic [destination]
mnemonic [destination], [source]
mnemonic [destination], [source1], [source2]
What are the 3 basic types of operands?
Immediate - uses a numeric literal expression
Register - uses a named register in the CPU
Memory - references a memory location
What are the simple notations for the standard operand types?
reg8 - 8-bit general purpose register reg16 - 16-bit general-purpose register reg32 - 32-bit general purpose register reg - any general-purpose register sereg - 16-bit segment register
imm - 8-, 16-, or 32-bit immediate value
imm8 - 8-bit immediate byte value
imm16 - 16-bit immediate word value
imm32 - 32-bit immediate doubleword value
reg/mem8 - 8-bit operand, either general register or memory byte
reg/mem16 - 16-bit operand, either general register or memory word
reg/mem32 - 32-bit operand, either general register or memory doubleword
mem - an 8-, 16-, or 32-bit memory operand
How can you use a direct memory operand to dereference a variable?
You can just move something from memory into a register, and read the machine code. For example, if you declared a variable var1, and it was offsetted at 10400h, you could copy it into an AL (8-bit) register
.data
var1 BYTE 10h
mov a1 var1
It would be assembled into the following machine instruction. The first byte in the machine instruction is the operation code (opcode), and the rest is the 32-bit hexadecimal address of var1.
A0 00010400
What are the rules for MOV instruction?
- Both operands MUST be the same size
- Both operands CANNOT be memory operands
- The instruction ponter register (IP, EIP, or RIP) cannot be a destination operand
MOV reg, reg MOV mem, reg MOV reg, mem MOV mem, imm MOV reg, imm
How would you use MOV to move data from memory to memory?
Even though you can’t do it directly, you can just assign the value of the memory to a register, and then move that value to another memory operand.
.data var1 WORD ? var2 WORD ? .code mov ax, var1 mov var2, ax
How can you copy smaller values to larger ones using MOV?
If it’s an unsigned integer, then you can just mov 0 to that register (ecx) and mov that integer to cx.
However, if you have a signed integer, then if you mov 0 to that register, then mov FFF0h (-16), you’ll get the wrong number (0000FFF0h). Therefore, you need to move 0FFFFFFFFh to the register, then mov FFF0h.
What can you do with the MOVZX instruction?
You can “move with zero-extend” any smaller unsigned integer to a larger memory. For example, if you moved 10001111b into AX.
mov bx, 0A698h
movzx eax, bx ; EAX = 0000A69Bh
movzx edx, b1 ; EDX = 0000009Bh
movzx cx, b1 ; CX = 009Bh
What can you do with the MOVSX instruction?
You can “move with sign-extend”, which will extend the value to 16 or 32 bits. It is ONLY used with signed integers.
mov bx, 0A69Bh
movsx eax, bx ; EAX = FFFFA69Bh
movsx edx, b1 ; EDX = FFFFFF9Bh
movsx cx, b1 ; CX = FF9Bh
What does the LAHF instruction do?
It “loads status flags into AH” by copying the low byte of the EFLAGS register into AH. The following flags are copied: Sign, Zero, Auxiliary Carry, Parity, and Carry. Using this, you can save a copy of the flags in a variable for safekeeping.
.data saveflags BYTE ? .code lahf ;load flags into AH mov saveflags, ah ; save them into a variable
What does the SAHF instruction do?
It “stores AH into status flags” by copying AH into the low byte of EFLAGS. You can use this to retrieve the value of flags saved in variables.
mov ah, saveflags ; load saved flags into ah
sahf ; copy into flags register
What does the XCHG instruction do? How can you exchange two memory operands with it?
It “exchanges data”, namely, the contents of two operands, the same as in MOV (no memory-to-memory) except that XCHG also does NOT accept ANY immediate operands.
XCHG reg, reg
XCHG reg, mem
XCHG mem, reg
If you want to exchange two memory operands, use a register as a temporary container and combine with MOV
mov ax, val1
xchg ax, val2
mov val1, ax
What are direct-offset operands and how do you use them with bytes?
You can add a displacement to the name of a variable to access memory locations that may not have explicit labels. For example, if we have an array of bytes called arrayB, then we can access each element with their “effective address”. However, there is NO built-in range checking!
arrayB BYTE 10h, 20h, 30h, 40h, 50h
mov al, arrayB ; AL = 10h
mov a1 [arrayB +1] ; AL = 20h
mov a1 [arrayB+2] ; AL = 30h
How do you use direct-offset operands with words and doublewords?
For words, you add 2 bytes to get the next element, and for doublewords, you add 4 bytes to get to the next element.
.data arrayW WORD 100h, 200h, 300h .code mov ax, arrayW ; AX = 100h mov ax, [arrayW + 2] ; AX = 200h
.data arrayD DWORD 10000h, 20000h .code mov eax, arrayD ; EAX = 10000h mov eax, [arrayD+4] ; EAX = 20000h
What do the INC and DEC instructions do?
The INC (increment) and DEC (decrement) instructions add 1 and subtract 1 from a register or memory operand.
.data myWord WORD 1000h .code inc myWord ; myWord = 1001h mov bx, myWord dec bx ; BX = 1000h
Although the Overflow, Sign, Zero, Auxiliary Carry, and Parity flags are changed, the INC and DEC instructions do NOT affect the Carry flag!!
What does the ADD instruction do?
ADD dest, source
For example, .data var1 DWORD 10000h var2 DWORD 20000h .code mov eax, var1 ; EAX = 10000h add eax, var2 ; EAX = 30000h
The Carry, Zero, Sign, Overflow, Auxiliary Carry, and Parity flags all change according to the destination value.
What does the SUB instruction do?
SUB dest, source
For example, .data var1 DWORD 30000h var2 DWORD 10000h .code mov eax, var1 ; EAX = 30000h sub eax, var2; EAX = 20000h
The Carry, Zero, Sign, Overflow, Auxiliary Carry, and Parity flags all change according to the destination value.
What does the NEG instruction do?
The NEG (negate) instruction reverses the sign of a register or memory operand by converting the number to its two’s complement.
NEG reg
NEG mem
The Carry, Zero, Sign, Overflow, Auxiliary Carry, and Parity flags all change according to the destination value.
How would you write what in C++ looks like this:
Rval = -Xval + (Yval - Zval);
If the following 32-bit variables are used:
Rval SDWORD ?
Xval SDWORD 26
Yval SDWORD 30
Zval SDWORD 40
First, negate a copy of Xval and store it in a register:
mov eax, Xval
neg eax ; EAX = -26
Second, copy Yval to a register and subtract Zval:
mov ebx, Yval
sub ebx, Zval
Third, add EBX to EAX and move that to Rval:
add eax, ebx
mov Rval, eax
How are the Carry, Overflow, and Zero status flags affected by addition and subtraction?
- The Carry flag indicates unsigned integer overflow. (e.g. if instruction has 8-bit destination operand but instruction generates something larger than 11111111, then Carry flag is set)
- Overflow flag indicates signed integer overflow. (e.g. if instruction has 16-bit destination operand but it generates negatives smaller than -32768 decimal, then Overflow flag is set)
- Zero flag indicates that an operation produced zero. For example, if an operand is subtracted from another of equal value, the Zero flag is set.
How are the Sign flag, Parity flag, and Auxiliary Carry flag affected by addition and subtraction?
- The Sign flag indicates an an operation produced a negative result (if the MSB is set).
- The Parity flag indicates whether or not an even number of 1 bits occurs in the least significant byte of the destination operand.
- The Auxiliary Carry flat is set when a 1-bit carries out of position 3 in the LSB of the destination operand.
How can there be a carry flag with subtraction?
A subtract operation sets the Carry flag when a larger unsigned integer is subtracted from a smaller one. For example, if we subtract 2 from 1, using 8-bit operands:
mov al, 1
sub al, 2 ; AL = FFh, CF = 1
Because it is negative, we have “carried” a 1 for the sign.
Can there be a carry flag with INC, DEC, or NEG?
The INC and DEC instructions do NOT affect the Carry flag.
However, applying the NEG instruction to a nonzero operand ALWAYS sets the Carry flag.
What is an example of an operation that sets off the auxiliary carry flag?
If you add 1 to 0Fh, then the sum 10h contains a 1 in bit position 4 that was carried out of bit position 3.
mov al, 0Fh
add al, 1 ; AC = 1
0 0 0 0 1 1 1 1
0 0 0 0 0001
——————-
0 0 0 1 0000
What is an example of an operation that sets of the Parity flag?
Since the Parity flag is set when the LSB has an even number of bits, you just need to figure out how to get an even number.
mov al, 10001100b
mov al, 00000010b ; AL = 10001110, PF = 1
mov al, 10000000b ; AL = 00001110, PF = 0
What does the Sign flag do mechanically?
Since the Sign flag is set when the result of a signed arithmetic operation is negative, it is just a copy of the destination operand’s highest bit.
mov bl, 1 ; BL = 01h
mov bl, 2 ; BL = FFh (-1), SF = 1
When can you know whether signed overflow has occurred, practically and mechanically?
Practically, it occurs in addition when:
1. Adding two positives makes a negative sum
2. Adding two negatives makes a positive sum
BUT it NEVER occurs when adding two different signs
Mechanically, the value that carries out of the highest bit position is XORed with the carry into the high bit of the result. For example, this produces CF =1 because 1 (carryOut) XOR 0 (carryIn) = 1.
1 0000000
+ 1 1 1 1 1 1 1 0
—————–
1 0 1 1 1 1 1 1 0
When does the NEG instruction produce an invalid result?
If the destination operand CANNOT be stored correctly. For example, if we move -128 to AL and try to negate it, the correct value (+128) will not fit into AL.
mov al, -128 ; AL = 10000000b
neg al ; AL = 10000000b, OF = 1
On the other hand, if +127 is negated, the result is valid and the Overflow flag is clear.
mov al, +127 ; AL = 01111111b
neg al ; AL = 10000001b, OF = 0
Write an instruction that increments val2.
val2 WORD 8000h
INC val2;
Write an instruction that subtracts val3 from EAX.
val3 DWORD 0FFFFh
SUB eax, val3;
Write instructions that subtract val4 from val2.
val2 WORD 8000h
val4 WORD 7FFFh
MOV ax, val4
SUB val2, ax
If val2 is incremented by 1 using the ADD instruction, what will be the values of the Carry and Sign flags?
val2 WORD 8000h
CF = 0 because there isn’t anything to carry here! It’ll just incremented to 8001h.
SF = 1 because the highest bit will be 1 (because 8 in binary is 1000.
If val4 is incremented by 1 using the ADD instruction, what will be the values of the Overflow and Sign flags?
val4 WORD 7FFFh
OF = 1 because the highest byte was 01111111, which means that it was the highest signed integer, and now it has to overflow into the MSB for the sign.
SF = 1 because now it has a “sign” when it didn’t have one before.
What are the values of the Carry, Sign, Zero, and Overflow flags after each instruction?
mov ax, 7FF0h
add al, 10h
add ah, 1
add ax, 2
add al, 10h
CF = 1 because F0 plus 10 has to equal 100h (not possible in 8-bit register).
ZF = 1 because now the bottom half is 0.
add ah, 1
SF = 1 because the top was 7F, or 01111111. When you add 1, it becomes 10000000, which has a “sign”.
add ax, 2
SF =1 because even though it’s now 8000h in ax overall, the MSB is still 1, making this technically negative.
What is a transfer of control or branch?
A way of altering the order in which statements are executed (JMP and LOOP).
What are the two basic types of transfers?
- Unconditional transfer (e.g. JMP) - control is transferred to a new location in all cases; a new address is loaded into the instruction pointer, causing execution to continue at the new address.
- Conditional transfer - the program branches if a certain condition is true. The CPU interprets true/false conditions based on the contents of the ECX and flags registers.
How do you implement JMP?
JMP destination
When the CPU executes an unconditional transfer, the offset of destination is moved into the instruction pointer, causing execution to continue at the new location.
How can you create an endless loop using JMP?
Just label some code the “top” and then say “jmp top”
top:
.
.
jmp top
How can you use the LOOP instruction?
LOOP destination
It automatically uses ECX as a counter and is decremented each time the loop repeats. The loop destination must be within -128 to +127 bytes of the current location counter.
After it subtracts 1 from ECX, if ECX is not zero, it jumps to the destination. If it is zero, then control passes to the next instruction.
How can you count ax from 0 to 5 using LOOP instruction?
Move 0 to ax, 5 to ecx, and then create a loop, inside of which you increment ax.
mov ax, 0
mov ecx, 5
L1:
inc ax
loop L1
BUT WATCH OUT! If you initialize ECX to 0, then you’ll have to repeat this loop 4,294,967,296 times until it decrements around to 0 again!
Why should you generally not modify ECX inside a loop?
You can end up with an endless loop. For example, this will increment ecx inside and decrement when it loops:
top: . . inc ecx loop top
What should you do if you need to modify ECX inside a loop?
You can save it in a variable (e.g. COUNT) at the beginning of the loop and restore it just before the LOOP instruction.
.code
mov ecx, 100
top: mov count, ecx . mov ecx, 20 . mov ecx, count loop top
How can you write a nested loop?
Save the original count in another variable, move the inner count into the variable, then after the inner loop, move the original count back into ecx.
mov ecx, 100 L1: mov count, ecx mov ecx, 20 L2: . . loop L2 mov ecx, count loop L1
How would you sum an integer array?
You need to assign the array’s address to an indexed register, initialize the loop counter to the length of the array, and assign zero to the register that accumulates the sum. Then, you need to create a label to make the loop, add a single element within the loop, and point to the next array element before repeating the loop.
intarray DWORD 10000h, 20000h, 30000h, 40000h
.code
main PROC
mov edi, OFFSET intarray ; EDI = address of intarray mov ecx, LENGTHOF intarray mov eax, 0
L1:
add eax,[edi]
add edi, TYPE intarray
loop L1
How would you copy a string?
source BYTE “This is the source string”,0
target BYTE SIZEOF source DUP(0)
.code
main PROC
mov esi, 0
mov ecx, SIZEOF source
L1: mov al, source[esi] mov target[esi], al inc esi loop L1
What are the two steps involved in executing a conditional statement?
- An operation such as CMP, AND, or SUB modifies the CPU status flags.
- A conditional jump instruction tests the flags and causes a branch to a new address.
How can you use the JZ instruction to do a conditional comparison?
CMP compares eax to 0, which sets the zero flag. Since JZ jumps to zero if zero flag was set, this jumps to L1.
cmp eax,0
jz L1
…
L1:
What are the J(cond) instructions and how do you use those?
J(cond) destination
There are four types:
- based on specific flag values
- based on equality between operands or (E)CX
- based on comparisons of unsigned operands
- based on comparisons of signed operands
e.g. je (jump if equal) is triggered when zero flag is set by CMP.
cmp eax, 5
je L1 ; jump if equal
What are the jumps based on specific flag values?
JZ - jump if zero (ZF = 1) JNZ - jump if not zero (ZF=0) JC - jump if carry (CF = 1) JNC - jump if not carry (CF = 0) JO - jump if overflow (OF = 1) JNO - jump if not overflow (OF = 0) JS - jump if signed (SF =1) JNS - jump if not signed (SF = 0) JP - jump if parity (PF = 1) JNP - jump if not parity (PF = 0)
How do jumps based on equality work?
First they use CMP leftOP, rightOP
Next, there are a number of jump instructions:
JE = jump if equal (same as JZ, jump if zero)
JNE = jump if not equal (same as JNZ, jump if not zero)
JCXZ = jump if CX = 0
JECXZ = jump if ECX = 0
Is the jump taken, and why?
mov edx, 0A523h
cmp edx, 0A523h
jne L5
je L1
The jump to L5 is NOT taken because they are equal, and jne jumps only if not equal.
The jump to L1 is taken because they are equal.
Is the jump taken, and why?
mov cx, 0FFFFh
inc cx
jcxz L2
Yes, the jump to L2 is taken because the increment makes cx overflow (if it could carry) to 0000h, which is equal to zero.
What are some jumps based on unsigned comparisons?
JA - jump if above (if leftOp > rightOp) JNBE - jump if not below or equal (same as JA) JAE - jump if above or equal JNB - jump if not below (i.e. JAE) JB - jump if below JNAE - jump if not above or equal (i.e. JB) JBE - jump if below or equal JNA - jump if not above (i.e. JBE)
What are some jumps based on signed comparisons?
JG - jump if greater JNLE - jump if not less than or equal JGE - jump if greater than or equal JNL - jump if not less (i.e. JGE) JL - jump if less JNGE - jump if not greater than or equal (i.e. JL) JLE - jump if less than or equal JNG - jmp if not greater (i.e. JLE)
Is the jump taken, and why?
mov al, +127
cmp al, -128
ja IsAbove
jg IsGreater
The jump to IsAbove is not taken because 7Fh is less than 80h.
However, the jump to IsGreater is taken because +127 is higher than -128.
Is the jump taken, and why?
mov edx, -1 cmp edx, 0 jnl L5 jnle L5 jl L1
The first jump to L5 is not taken because -1 is less than 0.
The second jump to L5 is not taken because -1 is less than and not equal to 0.
The third jump is taken because -1 is less than 0.
Is the jump taken, and why?
mov bx, +32 cmp bx, -35 jng L5 jnge L5 jge L1
The two jumps to L5 is not taken because 32 is greater than 35.
The last jump is taken because it is, indeed, greater.
What is the “test” instruction for and how do you use it?
You can test status bits. For example, if you want to jump if ANY of bit 0, 1, or 4 are set by status (of external device)
mov al, status
test al, 00010011bjnz InputDataByte
The following will also test whether or not ALL of the bits are set by status, using the AND instruction
mov al, status
and al, 10001100b
cmp al, 10001100b
je ResetMachine
How can you find the larger of two integers?
You can simply use the cmp instruction and jae instruction (if destination is above or equal to the source).
mov edx, eax ;assume EAX is larger cmp eax, ebx ; if EAX is above or equal to EBX jae L1 ; jmp to L1 mov edx, ebx ; else move EBX to EDX L1: ;EDX now has the larger integer
How can you find the smallest of three unsigned integers?
Use the cmp instruction between the first two, and then do another cmp and jbe for the third intger.
mov ax, V1 ;assume V1 is smallest cmp ax, V2 ;if AX is below or equal to V2 jbe L1 ;jump to L1 mov ax, V2 ;else move V2 to AX L1: cmp ax, V3 ;if AX is below or equal to V3 jbe L2 ;jump to L2 mov ax, V3 ;else move V3 to AX L2: ;AX now has the largest integer
How can you loop until a key is pressed?
The ReadKey method sets the Zero flag if no key is present in the input buffer. You need a 10 ms delay, because otherwise keystrokes might be ignored.
.data char BYTE ? .code L1: mov eax, 10 ;create 10 ms delay call Delay call ReadKey ;check for key jz L1 ;repeat if no key mov char, AL ; save the character
How do you do a sequential search of an array?
mov ebx, OFFSET intArray ;point to the Array
mov ecx, LENGTHOF intArray ;loop counter
L1: cmp WORD PTR[ebx], 0 ; compare a value to zero jnz found ;found a value add ebx, 2 ;point to next loop L1 ;continue the loop jmp notFound ;none found
found:
movsx eax, WORD PTR[ebx] ;sign-extend into EAX
call WriteInt
jmp quit
notfound:
mov edx, OFFSET noneMsg ;display “not found” message
call WriteString
quit:
call Crlf
exit