CPT101-Assembly Language

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.

1

2.1 Accessing Parts of Registers

2

3

类型大小
BYTE8 bits
WORD16 bits
DWORD32 bits
QWORD64 bits

2.2 Some Specialized Register Uses

  • General-Purpose

    • EAX – accumulator
    • ECX – loop counter
    • ESP – stack pointer
    • ESI, EDI – index registers
    • EBP – extended frame pointer (stack)
  • Segment

    • CS – code segment
    • DS – data segment
    • SS – stack segment
    • ES, 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)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小豪GO!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值