Kip Irvine 汇编语言 基于x86处理器 Chapter13 代码(含习题)

案例代码

01.addThree 外联汇编

test.asm

;测试函数 三个数相加 

.model flat, c

.code
	addThree_ proc
								;初始化栈帧指针
		push ebp
		mov ebp,esp
								;加载参数值
		mov eax,[ebp+8]
		mov ecx,[ebp+12]
		mov edx,[ebp+16]
								;求和
		add eax,ecx
		add eax,edx
								;恢复父函数的栈帧指针
		pop ebp
		ret
	addThree_ endp
end

main.cpp

//main.cpp 
#include <stdio.h>
#include <stdlib.h>

extern "C" int addThree_(int a, int b, int c);

int main()
{
	int a = 17;
	int b = 20;
	int c = 19;

	int sum = addThree_(a, b, c);

	printf("c = %d\n", sum);

	system("pause");
	return 0;
}

02.addThree 内嵌汇编

#include <stdio.h>
#include<stdlib.h>

int main()
{
    int a = 1, b = 2, c = 3;

    __asm//这里是双下划綫
    {
        push eax
        mov eax, a
        add eax, b
        add eax, c
        mov a, eax
        pop eax
    }

    printf("%d", a);
    system("pause");
    return 0;
}

03.findArray

findarr.h

// findarr.h

extern "C" 
{
	bool AsmFindArray(long n, long array[], long count);
	// Assembly language version
}

AsmFindArray.asm

TITLE FindArray Procedure      (AsmFindArray.asm)

; This version uses hand-optimized assembly language 
; code with the SCASD instruction. 

.586

.model flat,C

AsmFindArray PROTO,srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD

.code
    ;-----------------------------------------------
    AsmFindArray PROC USES edi,srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD
    ;
    ; Performs a linear search for a 32-bit integer
    ; in an array of integers. Returns a boolean 
    ; value in AL indicating if the integer was found.
    ;-----------------------------------------------
	    true    =   1
	    false   =   0

 	    mov	    eax,srchVal    			; search value
 	    mov	    ecx,count      			; number of items
 	    mov	    edi,arrayPtr   			; pointer to array

 	    repne	scasd           	    ; do the search
 	    jz	    returnTrue      		; ZF = 1 if found

    returnFalse:             
         mov	al, false     
         jmp	short exit

    returnTrue:
         mov	al, true

    exit:	
	    ret   
    AsmFindArray ENDP

END

main.cpp

// main.cpp - Testing the FindArray subroutine.

#include <stdlib.h>
#include <iostream>
#include "findarr.h"

using namespace std;

int main()
{
    const unsigned  ARRAY_SIZE          = 100   ;
    long            array[ARRAY_SIZE]           ;

    // Fill the array with pseudorandom integers.
    for (unsigned i = 0; i < ARRAY_SIZE; i++)
    {
        array[i] = rand();
        //cout << array[i] << " ";
    }

    cout << "\n\n";

    long searchVal;
    cout << "Enter an integer to find [0 to "<< RAND_MAX << "]: ";
    cin >> searchVal;

    if (AsmFindArray(searchVal, array, ARRAY_SIZE))
    {
        cout << "Your number was found.\n";
    }
    else
    {
        cout << "Your number was not found.\n";
    }
    return 0;
}

04.MultiplicationTable

subr.asm

; Multiplication Table program       (subr.asm)

; Calls external C++ functions.

INCLUDE Irvine32.inc

askForInteger	PROTO C
showInt			PROTO C, value:SDWORD, outWidth:DWORD



.data
	OUT_WIDTH		=		8
	ENDING_POWER	=		10
	intVal			DWORD	?

.code
	;---------------------------------------------
	SetTextOutColor PROC C,color:DWORD
	;
	; Sets the text colors and clears the console
	; window. Calls Irvine32 library functions.
	;---------------------------------------------
		mov		eax,color
		call	SetTextColor
		call	Clrscr
		ret
	SetTextOutColor ENDP

	;---------------------------------------------
	DisplayTable PROC C
	;
	; Inputs an integer n and displays a
	; multiplication table ranging from n * 2^1
	; to n * 2^10.
	;----------------------------------------------
		INVOKE		askForInteger			; call C++ function
		mov			intVal,eax            	; save the integer
		mov			ecx,ENDING_POWER       	; loop counter

	L1:	
		push		ecx                    	; save loop counter
		shl			intVal,1               	; multiply by 2
		INVOKE		showInt,intVal,OUT_WIDTH
		call		Crlf
		pop			ecx						; restore loop counter
		loop		L1

		ret
	DisplayTable ENDP
END

main.cpp

// main.cpp

// Demonstrates function calls between a C++ program
// and an external assembly language module.
// Last update: 6/24/2005

#include <iostream>
#include <iomanip>

using namespace std;

extern "C" 
{
	// external ASM procedures:
	void DisplayTable();
	void SetTextOutColor( unsigned color );

	// local C++ functions:
	int askForInteger();
	void showInt( int value, int width );
}

// program entry point
int main()
{
	SetTextOutColor( 0x1E );	// yellow on blue
	DisplayTable();				// call ASM procedure
	return 0;
}

// Prompt the user for an integer. 

int askForInteger()
{
	int n;
	cout << "Enter an integer between 1 and 90,000: ";
	cin >> n;
	return n;
}

// Display a signed integer with a specified width.

void showInt( int value, int width )
{
	cout << setw(width) << value;
}

05.Printf_Example

asmMain.asm

TITLE Test Floating - point output       (asmMain.asm)

	; Test the printf and scanf functions from the C library.
	; Test the printSingle function in the C++ module.

	INCLUDE Irvine32.inc

	; printSingle is a function in the startup C++ program,
	; which will be called from this module.

	printSingle PROTO C,aSingle:REAL4,precision : DWORD

	

	.code
	
			asmMain		PROC	C								; Entry point for this module

	;---------- test the printf function --------------
	; Note: do not pass REAL4 variables to printf using INVOKE

	.data
			TAB			=		9
			prompt		BYTE	"Enter a float, followed by a double: ",0
			formatTwo	BYTE	"%.2f",TAB,"%.3f",0dh,0ah,0
			val1		REAL8	456.789
			val2		REAL8	864.231

	.code
			INVOKE		printf, ADDR formatTwo, val1, val2

	;--------- test the scanf function -------------
	.data
			strSingle	BYTE	"%f",0
			strDouble	BYTE	"%lf",0
			float1		REAL4	1234.567
			double1		REAL8	1234567.890123

	.code

			; Input a float, then a double:
			INVOKE		printf, ADDR prompt

			INVOKE		scanf, ADDR strSingle, ADDR float1
			INVOKE		scanf, ADDR strDouble, ADDR double1

			;--------------------------------------------------------
			; Passing a single-precision value to printf is tricky
			; because it expects the argument to be a double.
			; The following code emulates code generated by Visual C++.
			; It may not make much sense until you read Chapter 17.

	.data
			valStr		BYTE	"float1 = %.3f",0dh,0ah,0
	.code
			fld			float1									; load float1 onto FPU stack
			sub			esp,8									; reserve runtime stack space
			fstp		qword ptr [esp]							; put on runtime stack as a double
			push		OFFSET	valStr
			call		printf
			add			esp,	12
	
	;----------------------------------------------------------
	; Call our a C function in the main program for printing single-precision.
	; Pass the number and the desired precision.

		INVOKE			printSingle, float1, 3
		call			Crlf
		
		ret
	asmMain ENDP

END

asmMain_stub.asm

TITLE Stub program for asmMain     (asmMain_stub.asm)

; Use this file as a starting point for creating a main
; ASM module called by C++. Its use is explained in the book
; in Section 12.3.4.1.

.386
.model flat,stdcall
.stack 2000

.code
asmMain PROC C

	ret
asmMain ENDP

END

main.cpp

// main.cpp


#include <stdio.h>
#include <iostream>

using namespace std;

extern "C" void asmMain( );
extern "C" void printSingle( float d, int precision );

void printSingle(float d, int precision)
{
	printf("%f", d);
}

/*
void printSingle( float d, int precision )
{
	strstream temp;
	temp << "%." << precision << "f" << '\0';
	printf(temp.str( ), d );
}*/


int main( )
{
	printf("Input an integer: ");
	int d;
	scanf("%d", &d);
	printf("Input a float, then a double: ");
	asmMain( );
	cout << "over!!";
	return 0;
}

06.DirectoryListing

asmMain.asm

; ASM program launched from C++    (asmMain.asm)
 
.586

.MODEL flat,C

    ; Standard C library functions:
    system      PROTO, pCommand:    PTR BYTE
    printf      PROTO, pString:     PTR BYTE,   args:VARARG
    scanf       PROTO, pFormat:     PTR BYTE,   pBuffer:        PTR BYTE, args:VARARG
    fopen       PROTO, mode:        PTR BYTE,   filename:       PTR BYTE
    fclose      PROTO, pFile:           DWORD

    BUFFER_SIZE = 5000
    .data
        str1        BYTE    "cls",0
        str2        BYTE    "dir/w",0
        str3        BYTE    "Enter the name of a file: ",0
        str4        BYTE    "%s",0
        str5        BYTE    "cannot open file",0dh,0ah,0
        str6        BYTE    "The file has been opened and closed",0dh,0ah,0
        modeStr     BYTE    "r",0

        fileName    BYTE    60 DUP(0)
        pBuf        DWORD   ?
        pFile       DWORD   ?

    .code
        asm_main PROC

                                            ; clear the screen, display disk directory
            INVOKE  system,ADDR str1
            INVOKE  system,ADDR str2
    
                                            ; ask for a filename
            INVOKE  printf,ADDR str3
            INVOKE  scanf, ADDR str4, ADDR fileName

                                            ; try to open the file
            INVOKE  fopen, ADDR fileName, ADDR modeStr
            mov     pFile,eax

            .IF     eax == 0                ; cannot open file?
              INVOKE    printf,ADDR str5
              jmp       quit
            .ELSE
              INVOKE    printf,ADDR str6
            .ENDIF

            ; Close the file
            INVOKE      fclose, pFile

        quit:
            ret                             ; return to C++ main
        asm_main ENDP
END 

startup.cpp

// startup.cpp

// stub module: launches assembly language program

extern "C" void asm_main();		// asm startup proc

void main()
{
	asm_main();
}


sample.txt

========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========

习题

Ex01

AsmMultArray.asm

title MultArray Procedure      (AsmMultArray.asm)

; This version uses hand-optimized assembly language 
; code with the SCASD instruction. 

.586
.model flat,C

AsmMultArray PROTO,
	srchVal:DWORD, arrayPtr:PTR DWORD, arraySize:DWORD

.code
;-----------------------------------------------
AsmMultArray PROC USES edi,
	mval:DWORD, arrayPtr:PTR DWORD, arraySize:DWORD
;
; Multiplies each element of an array by mval.
;-----------------------------------------------
 	mov	ebx,mval    		; multiplier
 	mov	ecx,arraySize      	; number of items
 	mov	edi,arrayPtr   	; pointer to array
 	
L1:	mov	eax,ebx			; get multiplier
	imul	eax, DWORD PTR[edi]	; multiply by array val
	mov	DWORD PTR[edi],eax	; store in the array
	add	edi,TYPE DWORD
	loop	L1
	
	ret   
AsmMultArray ENDP

END


multiarray.h

// multarray.h

extern "C" {

void AsmMultArray( long mval, long array[], long arraySize );
// Assembly language version

void MultArray( long mval, long array[], long arraySize );
// C++ version
}

multArray.cpp

// multArray.cpp


#include "multarray.h"

void MultArray( long mval, long array[], 
     long arraySize )
{
	for(int i = 0; i < arraySize; i++)
		array[i] *= mval;
}

main.cpp

// main.cpp - Testing the MultArray & AsmMultArray subroutines.

// Solution to Chapter 13 programming exercise 1.

#include <iostream>
#include <time.h>
#include "multarray.h"
using namespace std;

int main()
{
	// Fill an array with pseudorandom integers.
	const unsigned ARRAY_SIZE = 10000; 
	const unsigned LOOP_SIZE = 700000;

	long array[ARRAY_SIZE]; 
	for(unsigned i = 0; i < ARRAY_SIZE; i++)
     array[i] = rand();

	long mval = 55;		// multiplier
	time_t startTime;
	time_t endTime;
	int n;

// Test the C++ function:

	time( &startTime );

	for( n = 0; n < LOOP_SIZE; n++)
		MultArray( mval, array, ARRAY_SIZE );

	time( &endTime );
	cout << "Elapsed CPP time: " << long(endTime - startTime) 
		<< " seconds" << endl;

// Test the Assembly language version:

	time( &startTime );

	for( n = 0; n < LOOP_SIZE; n++)
		AsmMultArray( mval, array, ARRAY_SIZE );

	time( &endTime );
	cout << "Elapsed ASM time: " << long(endTime - startTime) 
		<< " seconds" << endl;

	return 0;
}

Ex02

longest.h

// longest.h

extern "C" {

unsigned  LongestIncreasingSequence( long array[], unsigned size );
// Assembly language version

}

Longest.asm

; LongestIncreasingSequence      (Longest.asm)

; Assembly language subroutine that receives two input parameters: the offset 
; of an array and the array's size. It must return a count of the longest 
; strictly increasing sequence of integer values. 

.586
.model flat,C

LongestIncreasingSequence PROTO,
	arrayPtr:PTR DWORD, arraySize:DWORD

MAX_INT = 2147483647

.code
;-----------------------------------------------
LongestIncreasingSequence PROC USES edi,
	arrayPtr:PTR DWORD, arraySize:DWORD
;
;-----------------------------------------------
	mov  ecx,0				; count
	mov  edx,0				; longest
	mov  esi,0				; i
	mov  ebx,MAX_INT		; prev 

L1:	cmp  esi,arraySize				; if i >= size, exit loop
	jae	 L4
	cmp  arrayPtr[esi*4],ebx
	jng  L2
	inc  ecx						;    count++
	cmp  ecx,edx					; if count > longest
	jna  L3
	mov  edx,ecx					;	longest = count
	jmp  L3

L2:									; else
	mov  ecx,1						;	count = 1

L3:
	mov  ebx,arrayPtr[esi*4]		; prev = array[i]
	inc  esi						; next array
	jmp	L1

L4:	mov  eax,edx					; return longest
	ret  
LongestIncreasingSequence ENDP

END


main.cpp

// main.cpp - Testing the LongestIncreasingSequence subroutine.

// Solution to Chapter 13 programming exercise 2.

#include <iostream>
#include "longest.h"
using namespace std;


// Optional: write the function in C++ to work out the algorithm.
unsigned LongestIncreasingSequenceCpp( long array[], unsigned size )
{
	unsigned count = 0;
	unsigned i = 0;
	long prev = INT_MAX;
	unsigned longest = 0;

	while( i < size ) {
		if( array[i] > prev ) {
			count++;
			if( count > longest )
				longest = count;
		}
		else
			count = 1;

		prev = array[i];
		i++;
	}
	return longest;
}

int main()
{
	const unsigned ARRAY_SIZE = 10; 
	long array[] = {-5, 10, 20, 14, 17, 26, 42, 22, 19, -5 };

// Test the Assembly language subroutine

	unsigned n = LongestIncreasingSequence( array, ARRAY_SIZE );
	
	cout << "The longest increasing sequence is " << n << endl;

	return 0;
}

Ex04

IsPrime.h


extern "C" {

bool IsPrime( int n );
// Assembly language version

}

IsPrime.asm

; Sum Three Arrays								 (sumarrays.asm)

COMMENT !
An assembly language procedure that returns a value of 1 if the 32-bit integer passed in the
EAX register is prime, and 0 if EAX is nonprime. Call this procedure from a high-level language
program. Let the user input a sequence of integers, and have your program display a message
for each one indicating whether or not it is prime. Suggestion: use the Sieve of Eratosthenes
algorithm to initialize a boolean array the first time your procedure is called. 
!

.586
.model flat,C
IsPrime PROTO,
	n:DWORD

.data
MAX = 100000
TRUE = 1
FALSE = 0
sieve BYTE MAX Dup(FALSE)
last DWORD ?
init DWORD FALSE

.code
;-----------------------------------------------
BuildSieve PROC USES eax esi edi
;-----------------------------------------------
	mov  esi,2			; i = 2

	mov  edx,0
	mov  eax,MAX		; last = MAX / i
	div  esi
	mov  last,eax

; while i < last
L1: cmp  esi,last
	jae  L6

	; j = i+i
	mov  edi,esi			; j = i
	add  edi,esi			; j += i

L2:	cmp  edi,MAX			; while j < MAX
	jae  L3
	mov  sieve[edi],TRUE	;	sieve[j] = true
	add  edi,esi			;	j += i
	jmp  L2

L3:	inc  esi				; i++

L4:	cmp  sieve[esi],TRUE	; while sieve[i] == true
	jne  L5
	cmp  esi,last			;    && i < last
	jae  L5
	inc  esi				;     i++
	jmp  L4

L5:	mov  eax,MAX			; last = MAX / i
	div  esi
	mov  last,eax

	jmp	 L1					; continue while loop

L6:	mov  init,TRUE
	ret
BuildSieve endp

;-----------------------------------------------
IsPrime PROC USES esi,
	n: DWORD
;-----------------------------------------------

	cmp  init,TRUE			; if !init
	je	 L1					;    call BuildSieve
	call BuildSieve

L1:
	mov  esi,n				; if sieve[n] == False
	cmp  sieve[esi],FALSE	;
	jne  L2
	mov  eax,TRUE			;   return true
	jmp  L3					; else
L2:	mov  eax,FALSE			;   return false
L3:	ret  
IsPrime ENDP

END

main.cpp

// main.cpp - Prime Number Program

// Solution to Chapter 13 programming exercise 4.

#include <iostream>
#include "IsPrime.h"
using namespace std;

const int MAX = 100;

/*
cool sieve[MAX] = {false};
bool init = false;

void buildSieve() {
	
	int i = 2;
	int last = MAX / i;

	while( i < last )  {
		for(int j = i+i; j < MAX; ) {
			sieve[j] = true;				// mark as non-prime
			j += i;
		}
		// i = next prime in the array
		i++;
		while( sieve[i] == true && i < last)
			i++;
		last = MAX / i;
	}
}

bool IsPrimeC( int n )
{
	if( !init )
		buildSieve();

	// Debugging: print the sieve:
	
	for(int i = 2; i < MAX; i++)
		if( !sieve[i] )
			cout << i << ",";
	cout << endl; 
	
	return !sieve[n];
}
*/

int main()
{
	int n;

	cout << "Enter an integer between 2 and " << MAX << ": ";
	cin >> n;
	
	if( IsPrime( n ) )
		cout << n << " is prime.\n";
	else
		cout << n << " is NOT prime.\n";

	
	return 0;
}

Ex05_LastIndexOf

LastIndexOf.asm

; IndexOf in Reverse      (LastIndexOf.asm)

; Searches backward through an array of integers for a
; matching value.

.586
.model flat,C

LastIndexOf PROTO,
	srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD

.code
;-----------------------------------------------
LastIndexOf PROC USES edi,
	srchVal:DWORD, arrayPtr:PTR DWORD, count:DWORD
;
; Performs a reverse linear search for a 32-bit integer
; in an array of integers. Returns a boolean 
; value in AL indicating if the integer was found.
;-----------------------------------------------
	true = 1
	false = 0

	mov	eax,4			; eax = (count-1)*4
	mov	ebx,count
	dec	ebx
	mul	ebx
	mov	edi,arrayPtr
	add	edi,eax			; edi points to last array element

 	mov	eax,srchVal    	; search value
 	mov	ecx,count      	; number of items

L1: 	mov	eax,[edi]			; get an element
 	cmp	eax,srchVal		; compare it to the search value
 	je	returnTrue		; if equal, return true
 	sub	edi,4			; otherwise, back up through the array
 	loop	L1

returnFalse:             
     mov	al,false     
     jmp	short exit

returnTrue:
     mov	al, true

exit:	
	ret   
LastIndexOf ENDP

END


main.cpp

// Chapter 12, Exercise 6					(main.cpp)

// Tests the FindRevArray procedure, written in assembly language.

#include <iostream>
#include <time.h>
using namespace std;

extern "C" bool LastIndexOf( long searchVal, long array[], unsigned count );

int main()
{
	// Fill an array with pseudorandom integers. Loop 10 billion times.
	const unsigned ARRAY_SIZE = 100000; 
	const unsigned LOOP_SIZE = 100000;

	long array[ARRAY_SIZE]; 
	for(unsigned i = 0; i < ARRAY_SIZE; i++)
		array[i] = rand();

	long searchVal;
	time_t startTime, endTime;
	cout << "Enter value to find: ";
	cin >> searchVal;
	cout << "Please wait. This will take between 10 and 20 seconds...\n";

// Call the assembly language function:

	time( &startTime );
	bool found = false;

	for( int n = 0; n < LOOP_SIZE; n++)
		found = LastIndexOf( searchVal, array, ARRAY_SIZE );

	time( &endTime );
	cout << "Elapsed CPP time: " << long(endTime - startTime)
		<< " seconds." << endl;

	if( found )
		cout << "The number was found\n";
	else
		cout << "Not found\n";

	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值