文章目录
- 1. Inline Assembler
- 2. General-Purpose Registers
- 3. Instruction
- 4. Flow Controls
- Example
- 1. Summing an Integer Array
- 2. Copying a String
- 3. calculates the sum of the integers
- 5. finds the first positive value
- 6. Bubble Sort
- 7. Hello World
- 9. Register Indirect mode in Arrays
- 10. Alternative array handling
- 12. Practical Exercise 2
- 13. Handling Character
- 15. Compare and Jump
- 16. Using Stack
- EBP and ESP for stack frames
- Stack frame
1. Inline Assembler
- Inline means you can insert assembly codes directly into C/C++ programs, compile and execute them.
_asm mov eax,var ; stores the value of
; var in EAX
; or
_asm
{
....
}
- One can use
_asm
without brackets, in that case it works only for one line. - Semicolon
;
is used for the comments in the assembly program. Alternatively, one can use//
for the comments. - An
_asm { … …}
block can call C functions, including C library routines.
2. General-Purpose Registers
Named storage locations inside the CPU, optimized for speed.
2.1 Accessing Parts of Registers
类型 | 大小 |
---|---|
BYTE | 8 bits |
WORD | 16 bits |
DWORD | 32 bits |
QWORD | 64 bits |
2.2 Some Specialized Register Uses
-
General-Purpose
EAX
– accumulatorECX
– loop counterESP
– stack pointerESI
,EDI
– index registersEBP
– extended frame pointer (stack)
-
Segment
CS
– code segmentDS
– data segmentSS
– stack segmentES
,FS
,GS
- additional segments
-
EIP
– instruction pointer -
EFLAGS
- status and control flags
- each flag is a single binary bit
3. Instruction
We use the Intel IA-32 instruction set
-
An instruction contains:
- Label (optional)
- Mnemonic (required)
- Operand (depends on the instruction)
- Comment (optional)
-
Code label
- target of jump and loop instructions
- example:
L1:
3.1 Mnemonics and Operands
-
Instruction Mnemonics
- memory aid
- examples:
MOV
,ADD
,SUB
,MUL
,INC
,DEC
,NEG
-
Operands
- constant
- constant expression
- register
- memory (data label)
Constants and constant expressions are often called immediate values
####3.1.1 LEA (load effective address)
lea eax a ;是将a的地址复制到寄存器eax
####3.1.2 MOV (move)
mov eax a ;是将a的值赋值给寄存器eax
-
Move from source to destination. Syntax:
- MOV destination,source
-
No more than one memory operand permitted
-
CS, EIP, and IP cannot be the destination
-
No immediate to segment moves
3.2 Useful Operators
3.2.1 OFFSET
- The value returned by OFFSET is a pointer
mov esi,OFFSET bVal ; ESI = 00404000
3.2.2 TYPE
- returns the size, in bytes, of a single element of a data declaration.
var1 BYTE ?
mov eax,TYPE var1 ; 1
3.2.3 LENGTHOF
- counts the number of elements in a single data declaration.
.data LENGTHOF
byte1 BYTE 10,20,30 ; 3
array1 WORD 30 DUP(?),0,0 ; 32
array2 WORD 5 DUP(3 DUP(?)) ; 15
array3 DWORD 1,2,3,4 ; 4
digitStr BYTE "12345678",0 ; 9
.code
mov ecx,LENGTHOF array1 ; 32
x DUP(y)
: 将 y 重复 x 次
3.2.4 SIZEOF
- returns a value that is equivalent to multiplying LENGTHOF by TYPE.
array1 WORD 30 DUP(?),0,0 ; 64
mov ecx,SIZEOF array1 ; 64
4. Flow Controls
4.1 JMP
JMP is an unconditional jump to a label that is usually within the same procedure.
top:
.
.
jmp top
4.2 Loop Instruction
- Logic:
- ECX ← ECX – 1
if ECX != 0, jump to target
target:
.
.
.
LOOP target
mov ax,0
mov ecx,5
L1: add ax,cx
loop L1
4.3 CMP
Syntax: CMP destination, source
- Example: destination == source
mov al,5
cmp al,5 ; Zero flag set
- Example: destination < source
mov al,4
cmp al,5 ; Carry flag set
- Example: destination > source
mov al,6
cmp al,5 ; ZF = 0, CF = 0
- Example: destination > source
mov al,5
cmp al,-2 ; Sign flag == Overflow flag
- Example: destination < source
mov al,-1
cmp al,5 ; Sign flag != Overflow flag
4.4 Conditional Jumps
- Jumps Based On . . .
- Specific flags
- Equality
- Unsigned comparisons
- Signed Comparisons
4.4.1 Jcond
A conditional jump instruction branches to a label when specific register or flag conditions are met
- Specific jumps:
- JB, JC - jump to a label if the Carry flag is set
- JE, JZ - jump to a label if the Zero flag is set
- JS - jump to a label if the Sign flag is set
- JNE, JNZ - jump to a label if the Zero flag is clear
- JECXZ - jump to a label if ECX = 0
4.5 Conditional Loop Instructions
- LOOPZ and LOOPE
- LOOPNZ and LOOPNE
4.5.1 LOOPZ and LOOPE
•Syntax:
LOOPE destination
LOOPZ destination
•Logic:
•ECX ←ECX – 1
•if ECX > 0 and ZF=1, jump to destination
•Useful when scanning an array for the first element that does not match a given value.
Example
1. Summing an Integer Array
.data
intarray WORD 100h,200h,300h,400h
.code
mov edi,OFFSET intarray ; address of intarray
mov ecx,LENGTHOF intarray ; loop counter
mov ax,0 ; zero the accumulator
L1:
add ax,[edi] ; add an integer
add edi,TYPE intarray ; point to next integer
loop L1 ; repeat until ECX = 0
2. Copying a String
.data
source BYTE "This is the source string",0
target BYTE SIZEOF source DUP(0)
.code
mov esi,0 ; index register
mov ecx,SIZEOF source ; loop counter
L1:
mov al,source[esi] ; get char from source
mov target[esi],al ; store it in the target
inc esi ; move to next character
loop L1 ; repeat for entire string
3. calculates the sum of the integers
5 + 4 + 3 +2 + 1:
offset machine code source code
00000000 66 B8 0000 mov ax,0
00000004 B9 00000005 mov ecx,5
00000009 66 03 C1 L1: add ax,cx
0000000C E2 FB loop L1
0000000E
###4. Nested Loop
.data
count DWORD ?
.code
mov ecx,100 ; set outer loop count
L1:
mov count,ecx ; save outer loop count
mov ecx,20 ; set inner loop count
L2: .
.
loop L2 ; repeat the inner loop
mov ecx,count ; restore outer loop count
loop L1 ; repeat the outer
mov ecx,100 ; set outer loop count
L1: ; begin the outer loop
push ecx ; save outer loop count
mov ecx,20 ; set inner loop count
L2: ; begin the inner loop
;
;
loop L2 ; repeat the inner loop
pop ecx ; restore outer loop count
loop L1 ; repeat the outer loop
5. finds the first positive value
.data
array SWORD -3,-6,-1,-10,10,30,40,4
sentinel SWORD 0
.code
mov esi,OFFSET array
mov ecx,LENGTHOF array
next:
test WORD PTR [esi],8000h ; test sign bit
pushfd ; push flags on stack
add esi,TYPE array
popfd ; pop flags from stack
loopnz next ; continue loop
jnz quit ; none found
sub esi,TYPE array ; ESI points to value
quit:
6. Bubble Sort
BubbleSort PROC USES eax ecx esi,
pArray:PTR DWORD,Count:DWORD
mov ecx,Count
dec ecx ; decrement count by 1
L1: push ecx ; save outer loop count
lea esi,pArray ; point to first value
L2: mov eax,[esi] ; get array value
cmp [esi+4],eax ; compare a pair of values
jge L3 ; if [esi] <= [edi], skip
xchg eax,[esi+4] ; else exchange the pair
mov [esi],eax
L3: add esi,4 ; move both pointers forward
loop L2 ; inner loop
pop ecx ; retrieve outer loop count
loop L1 ; else repeat outer loop
L4: ret
BubbleSort ENDP
7. Hello World
/* demonstration of the use of asm instructions within a C program */
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char format[] = "Hello World\n“; // declare variables in C
_asm{
mov ecx,10 // initialize loop counter
Lj: push ecx // loop count index saved on stack
lea eax,format // load the address of the array
push eax // address of string, stack parameter
call printf // use library code subroutine
add esp,4 // clean 4 byte parameter off stack
pop ecx // restore loop counter ready for test
loop Lj // dec ECX, jmp back if ECX nonzero
} // back to C
return 0;
}
###8. Passing parameters
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char format[] = "Hello World\n"; // declare variables in C
_asm{
mov ecx,10 // initialize loop counter
Lj: push ecx // loop count index saved on stack
lea eax,format // load the address of the array
push eax // address of string, stack parameter
call printf // use library code subroutine
add esp,4 // clean 4-byte parameter off stack
// same as printf ("Hello World\n“)in C
pop ecx // restore loop counter ready for test
loop Lj // dec ECX, jmp back if ECX nonzero
} // back to C
return 0;
}
9. Register Indirect mode in Arrays
int myarray[5]; // declaration of an array of integers
myarray[0] = 1; //
myarray[1] = 3; //
myarray[2] = 5; // initialise the array
myarray[3] = 7; //
myarray[4] = 9; //
_asm
{
…
lea ebx,myarray
// address of the array (its 0th element) is saved in ebx
mov ecx,5 // size of the array is saved in the counter
mov eax,0 // eax will be used to store the sum, initialise to 0
loop1: add eax,[ebx]
// read an element of the array at the address stored in ebx
add ebx,4 // int occupies 4 bytes (32 bits),
// so to read next element increase the address in ebx by 4
loop loop1 // end of the loop
}
10. Alternative array handling
int myarray[5]; // declaration of an array of integers
myarray[0] = 1; //
myarray[1] = 3; //
myarray[2] = 5; // initialise the array
myarray[3] = 7; //
myarray[4] = 9; //
_asm{
mov ecx,5 // size of the array is saved in the counter
mov eax,0 // eax will be used to store the sum, initialise to 0
mov ebx,0
loop1:
add eax,myarray[ebx] // read an element of the array at the
// address myarray + ebx
add ebx,4 // int occupies 4 bytes (32 bits), so to read
// next element increase the address in ebx
// by 4
loop loop1 // end of the loop
}
###11. Practical Exercise 1
#include <iostream>
int main()
{
char message1[] = "Give me a first number: ";
char message2[] = "\bGive me a second number: ";
char message3[] = "\nThe numbers are equal!\n";
char message4[] = "\nThe numbers are not equal!\n";
char message5[] = "Type in any integer and press ENTER key to finish: ";
char format[] = "%d"; // format string for the scanf function
int first;
int second;
int end;
_asm{
lea eax, message1
push eax
call printf ; printing the first message
add esp, 4
lea eax, first
push eax
lea eax, format
push eax
call scanf_s ; reading the first number
add esp, 8
lea eax, message2
push eax
call printf ; printing the second message
add esp, 4
lea eax, second
push eax
lea eax, format
push eax
call scanf_s ; reading the second number
add esp, 8
mov eax, first
sub eax, second ; compare two numbers, jump to nequal if flag is not zero
jnz nequal
equal:
lea eax, message3
push eax
call printf ; printing the third message
add esp, 4
jmp finish
nequal:
lea eax, message4
push eax
call printf ; printing the fourth message
add esp, 4
finish:
lea eax, message5
push eax
call printf ; printing the fifth message
add esp, 4
lea eax, end
push eax
lea eax, format
push eax
call scanf_s ; reading any integer to end program
add esp, 8
}
return 0;
}
12. Practical Exercise 2
#include <iostream>
int main()
{
char message1[] = "Give me a first number: ";
char message2[] = "\bGive me a second number: ";
char message3[] = "\nThe numbers are equal!\n";
// char message4[] = "\nThe numbers are not equal!\n";
char message5[] = "Type in any integer and press ENTER key to finish: ";
char format[] = "%d"; // format string for the scanf function
char message6[] = "\nThe first number is greater!\n"; // new addition
char message7[] = "\nThe second number is greater!\n"; // new addition
int first;
int second;
int end;
_asm{
lea eax, message1
push eax
call printf ; printing the first message
add esp, 4
lea eax, first
push eax
lea eax, format
push eax
call scanf_s ; reading the first number
add esp, 8
lea eax, message2
push eax
call printf ; printing the second message
add esp, 4
lea eax, second
push eax
lea eax, format
push eax
call scanf_s ; reading the second number
add esp, 8
mov eax, first
mov ebx, second
cmp eax, ebx ; compare two numbers, jump to nequal if flag is not zero
jg firstNumGreater
jl secondNumGreater
equal:
lea eax, message3
push eax
call printf ; printing the third message
add esp, 4
jmp finish
firstNumGreater:
lea eax, message6
push eax
call printf ; printing the sixth message
add esp, 4
jmp finish
secondNumGreater:
lea eax, message7
push eax
call printf ; printing the seventh message
add esp, 4
finish:
lea eax, message5
push eax
call printf ; printing the fifth message
add esp, 4
lea eax, end
push eax
lea eax, format
push eax
call scanf_s ; reading any integer to end program
add esp, 8
}
return 0;
}
13. Handling Character
#include <iostream>
int main()
{
char scanf_fmt[] = "%c";
char printf_fmt[] = "%c\n";
char character;
_asm {
push 1 // Buffer size, you can also write `push size character`
lea eax, character
push eax // Pointer to character
lea eax, scanf_fmt
push eax // Pointer to format string
call scanf_s
add esp, 12 // Clean up three pushes
movzx eax, byte ptr[character] // MOVZX: Load one unsigned byte into a 32-bit-register
push eax // Character as value
lea eax, printf_fmt
push eax // Pointer to format string
call printf
add esp, 8 // Clean up two pushes
}
return 0;
}
###14. Total Amount and ECX Loop
#include <iostream>
int main()
{
char msgTotalAmt[] = "Total amount is %d\n\n";
int testArray[3] = { 8, 6, 4 };
// _int16 test = -50;
int loopCounter = 3;
int totalAmt = 0;
_asm{
lea esi, testArray
mov ecx, loopCounter
addLoop:
mov eax, [esi]
add totalAmt, eax
add esi, 4
loop addLoop
mov eax, totalAmt
push eax
lea eax, msgTotalAmt
push eax
call printf
add esp, 8
}
return 0;
}
15. Compare and Jump
#include <iostream>
int main()
{
char msgSelectPositiveInt[] = "Select total number of positive integers (between 2-5): ";
char msgEnterPositiveInt[] = "Enter positive integer %d: ";
char msgProgEnds[] = "\nProgram terminates and has looped %d times.\n\n";
char msgListInt[] = "Your integers from lowest to highest are ";
char msgComma[] = " , ";
char msgTotalAmt[] = "\n\nThe total amount is %d \n\n";
char format[] = "%d"; // format string for the scanf function
int totalNumInt;
int intList[5];
int cntNumInt = 0;
int positiveInt;
int totalAmt = 0;
_asm{
readTotalPositiveInt:
lea eax, msgSelectPositiveInt
push eax
call printf ; print message requesting user to enter total number of positive integers
add esp, 4
lea eax, totalNumInt
push eax
lea eax, format
push eax
call scanf_s ; read user input of total number of positive integers
add esp, 8
mov eax, totalNumInt
cmp eax, 5
jg readTotalPositiveInt ; loop back if input is more than 5
cmp eax, 2
jl readTotalPositiveInt ; loop back if input is less than 2
lea esi, intList ; load memory address of the first item in integer array into esi register
readIntList:
inc cntNumInt
mov eax, cntNumInt
cmp totalNumInt, eax ; compare total number of positive integers with current count
js printNumLoop ; if total number of positive integers is less than current count, jump to print number of loops message
push eax
lea eax, msgEnterPositiveInt
push eax
call printf ; print message for user to enter a positive integer one at a time
add esp, 8
lea eax, positiveInt
push eax
lea eax, format
push eax
call scanf_s ; read user input of a positive integer
add esp, 8
cmp positiveInt, 0 ; compare user input with zero
js printNumLoop ; if user enters a negative integer, jump to print number of loops message
mov eax, positiveInt
mov [esi], eax ; otherwise move user input of a positive integer into memory address pointed by esi register
add esi, 4 ; incrememt memory address by 4-byte as pointed by esi register
jmp readIntList ; loop back to process next positive integer
printNumLoop:
dec cntNumInt
mov ebx, cntNumInt
push ebx
lea ebx, msgProgEnds
push ebx
call printf ; print program ends and number of loops message
add esp, 8
mov ecx, cntNumInt ; save number of positive integers into ecx register
cmp ecx, 0 ; check if user input zero number
je finish ; if equal, jump to print total amount
cmp ecx, 1 ; check if user input only 1 number
je printSortedIntMsg ; if equal, jump to print sorted integers
dec ecx
L1:
push ecx ; save outer loop count
lea esi, intList ; load memory address of the first item in integer array into esi register
L2:
mov eax, [esi] ; load the content of memory address pointed by esi register
cmp [esi+4], eax ; compare the contents between adjacent memory addresses
jge L3 ; if [esi+4] >= [esi], skip to outer loop
xchg eax, [esi+4] ; otherwise exchange the contents between adjacent memory addresses
mov [esi], eax ; continue with the exchange via eax register
L3 :
add esi, 4 ; move pointer to next memory address of the integer array
loop L2 ; continue with inner loop
pop ecx ; retrieve outer loop count
loop L1 ; else repeat outer loop
printSortedIntMsg:
lea eax, msgListInt
push eax ; printing messsage listing sorted integers
call printf
add esp, 4
mov ebx, cntNumInt
dec ebx
lea esi, intList ; load memory address of the first item in integer array into esi register
printSortedInt:
cmp ebx, 0
js printTotalAmt
mov eax, [esi]
push eax
lea eax, format
push eax
call printf ; print positive integers in reverse
add esp, 8
cmp ebx, 1
js skipLastComma ; skip from printing comma if it is the last integer
lea eax, msgComma
push eax
call printf ; print comma to separate integer list
add esp, 4
skipLastComma:
add esi, 4
dec ebx
jmp printSortedInt
printTotalAmt:
lea edi, intList ; load memory address of the first item in integer array into edi register
mov ecx, cntNumInt ; save number of positive integers into ecx register
mov eax, totalAmt ; set total amount to zero
addPositiveInt:
add eax, [edi] ; add positive integer
add edi, 4 ; point to next positive integer
loop addPositiveInt
push eax
lea ebx, msgTotalAmt
push ebx
call printf ; print total amount message
add esp, 8
finish:
}
return 0;
}
16. Using Stack
#include <iostream>
#include "string.h"
#define MAX_SZ 6
int main()
{
char myArray[MAX_SZ] = "Hello";
char newArray[MAX_SZ];
memset(newArray, 0, sizeof(newArray)); // initialize myName char array to empty string
_asm{
mov ecx, MAX_SZ-1
mov esi, 0
pushIt:
movzx eax, myArray[esi] ; move each char to eax register
push eax ; push char onto stack
inc esi ; increment index counter
loop pushIt
mov ecx, MAX_SZ-1 ; reset loop counter with MAX_SZ
mov esi, 0 ; reset index counter
popIt :
pop eax ; pop char out from stack in reverse
mov newArray[esi], al ; store char back into myArray
inc esi ; increment index counter
loop popIt
lea eax, newArray
push eax
call printf
add esp, 4
}
return 0;
}
EBP and ESP for stack frames
- EBP: The stack frame base pointer.
- To indicate the base of the current stack frame.
- ESP: The stack pointer.
- To hold the address of the top of the stack.
Stack frame
- The area of the stack which holds all the data related to one call of a subroutine.
- The data includes:
- Parameters of the subroutine.
- Return address.
- Old stack pointer contents (EBP)
- Local variables.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z0QgnWLZ-1673368251262)(…/…/AppData/Roaming/Typora/typora-user-images/image-20230110010452545.png)]