• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

武飞扬头像
dos diosas
帮助1

案例代码

01.SHL逻辑左移指令的应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;简单的操作
		mov		bl,8Fh		;BL=1000 1111b
		shl		bl,1		;CF=1  BL=0001 1110b

		mov		al,80h		;BL=1000 0000b
		shl		al,2		;CF=0  BL=0000 0000b
		;当一个数字多次移位的时候,进位标志位是MSB

		;使用左移进行位元乘法
		mov		dl,5		;移动前:0000 0101
		shl		dl,1		;移动后:0000 1010

		mov		dl,5		;移动前:0000 0101
		shl		dl,2		;移动后:0001 0100

		invoke ExitProcess,0
	main ENDP
END main
学新通

02.SHR逻辑右移指令的应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;简单的操作
		mov		bl,8Fh		;BL=1000 1111b
		shr		bl,1		;CF=1  BL=0100 0111b

		mov		al,80h		;BL=1000 0000b
		shr		al,2		;CF=0  BL=0010 0000b
		;当一个数字多次移位的时候,进位标志位是最后移除的最高/低有效位

		;使用右移进行位元除法
		mov		dl,5		;移动前:0000 0101
		shr		dl,1		;移动后:0000 0010

		mov		dl,5		;移动前:0000 0101
		shr		dl,2		;移动后:0000 0001

		invoke ExitProcess,0
	main ENDP
END main
学新通

03.SAL算术左移指令的应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;简单的操作
		mov		bl,8Fh		;BL=1000 1111b
		sal		bl,1		;CF=1  BL=0001 1110b

		mov		al,80h		;BL=1000 0000b
		sal		al,2		;CF=0  BL=0000 0000b
		;当一个数字多次移位的时候,进位标志位是MSB

		;使用左移进行位元乘法
		mov		dl,5		;移动前:0000 0101
		sal		dl,1		;移动后:0000 1010

		mov		dl,5		;移动前:0000 0101
		sal		dl,2		;移动后:0001 0100

		invoke ExitProcess,0
	main ENDP
END main
学新通

04.SAR算术右移指令的应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;简单的操作
		mov		bl,8Fh		;BL=1000 1111b
		sar		bl,1		;CF=1  BL=1100 0111b

		mov		al,80h		;AL=1000 0000b
		sar		al,2		;CF=1  AL=1110 0000b

		invoke ExitProcess,0
	main ENDP
END main
学新通

05.有符号除法


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;使用SAR指令,就可以将有符号操作数除以2的幂
		mov dl,-128		;DL=1000 0000b
		sar dl,3		;DL=1111 0000b	这是-16的补码

		invoke ExitProcess,0
	main ENDP
END main
学新通

06.AX扩展到EAX


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		mov	ax,-128		;EAX=????FF80h
		shl eax,16		;EAX=FF800000h
		sar eax,16		;EAX=FFFFFF80h

		invoke ExitProcess,0
	main ENDP
END main
学新通

07.ROL指令及其应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		;简单的循环左移  实际上是将CF标志位的值存放在被移位的值末尾
		mov	al,40h		;AL=0100 0000b
		rol al,1		;AL=1000 0000b	CF=0
		rol al,1		;AL=0000 0001b  CF=1
		rol al,1		;AL=0000 0010b  CF=0

		;循环多次左移
		mov al,00100000b
		rol al,3		;AL=0000 0001b  CF=1

		;位组交换		使用ROL ROR指令可以将一个字节的高四位和低四位进行交换
		mov al,62h	
		rol	al,4		;AL=26h

		;当多字节这整数以四位为单位进行循环移位的时候,其效果相当于一次性向右
		;或者向左移动一个十六进制位
		mov	ax,6A4Bh
		rol ax,4		;AX=A4B6h
		rol	ax,4		;AX=4B6Ah
		rol ax,4		;AX=B6A4h
		rol ax,4		;AX=6A4Bh

		invoke ExitProcess,0
	main ENDP
END main
学新通

08.ROR指令及其应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		;简单的循环右移  实际上是将CF标志位的值存放在被移位的值末尾
		mov	al,40h		;AL=0100 0000b
		ror al,1		;AL=0010 0000b	CF=0
		ror al,1		;AL=0001 0000b  CF=0
		ror al,1		;AL=0000 1000b  CF=0

		;循环多次右移
		mov al,00100000b
		ror al,3		;AL=0000 0100b  CF=0

		;位组交换		使用ROL ROR指令可以将一个字节的高四位和低四位进行交换
		mov al,62h	
		ror	al,4		;AL=26h

		;当多字节这整数以四位为单位进行循环移位的时候,其效果相当于一次性向右
		;或者向左移动一个十六进制位
		mov	ax,6A4Bh
		ror ax,4		;AX=B6A4h
		ror	ax,4		;AX=4B6Ah
		ror ax,4		;AX=A4B6h
		ror ax,4		;AX=6A4Bh

		invoke ExitProcess,0
	main ENDP
END main
学新通

09.RCL带进位循环左移


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	testVal	BYTE	01101010b

.code
	main PROC
		
		;本指令使用之前应当先清除标志位
		clc						;CF=0
		mov	bl,88h				;CF=0  BL=88  1000 1000h
		rcl bl,1				;CF=1  BL=10  0001 0000h
		rcl bl,1				;CF=0  BL=21  0010 0001h
		
		;从进位标志位复位
		shr	testVal,1			;将LSB移入进位标志位  testVal=0011 0101b
		jc	exit				;如果仅为标志位=1则跳转
		rcl testVal,1			;否则从CF那里开始循环左移恢复原值

		exit:

		invoke ExitProcess,0
	main ENDP
END main
学新通

10.RCR带进位循环右移


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	testVal	BYTE	01101010b

.code
	main PROC
		
		;本指令使用之前应当先清除标志位
		clc						;CF=0
		mov	bl,88h				;CF=0  BL=88  1000 1000h
		rcr bl,1				;CF=0  BL=44  0100 0100h
		rcr bl,1				;CF=0  BL=22  0010 0010h
		
		;从进位标志位复位
		shl	testVal,1			;将LSB移入进位标志位  testVal=1101 0100b
		jc	exit				;如果仅为标志位=1则跳转
		rcr testVal,1			;否则从CF那里开始循环左移恢复原值

		exit:

		invoke ExitProcess,0
	main ENDP
END main
学新通

11.有符号数的溢出问题


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		mov al, 127	;AL=01111111b
		rol al,1	;OF=1 AL=11111110b

		mov al,-128	;AL=10000000b
		shr al,1	;OF=1 AL=01000000b

		invoke ExitProcess,0
	main ENDP
END main
学新通

12.SHLD指令


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	wval	WORD	9BA6h
		
.code
	main PROC

		mov		ax,0AC36h
		shld	wval,ax,4	;wval=BA6A

		invoke ExitProcess,0
	main ENDP
END main
学新通

13.SHRD指令


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	wval	WORD	9BA6h
		
.code
	main PROC

		mov		ax,0AC36h
		shrd	wval,ax,4	;wval=69BAh

		mov		ax,234Bh
		mov		dx,7654h
		shrd	ax,dx,8		;ax=5423h

		invoke ExitProcess,0
	main ENDP
END main
学新通

14.SHRD的应用 将双字数组右移4位

; SHRD Example             (Shrd.asm)

Comment !
This program shifts an array of five 32-bit integers using the SHRD 
instruction. It shifts a series of consecutive doublewords 4 bits 
to the right. The number is in little Endian order.
!

INCLUDE Irvine32.inc

COUNT = 4							; shift count

.data
array DWORD 648B2165h,8C943A29h,6DFA4B86h,91F76C04h,8BAF9857h

.code
main PROC

	mov  bl,COUNT
	call ShiftDoublewords

; Display the results
	mov  esi,OFFSET array
	mov  ecx,LENGTHOF array
	mov  ebx,TYPE array
	call DumpMem

	exit
main ENDP

;---------------------------------------------------------------
ShiftDoublewords PROC
;
; Shifts an array of doublewords to the right.
; The array is a global variable.
; Receives: BL = number of bits to shift
; Returns: nothing
;---------------------------------------------------------------
	mov  esi,OFFSET array
	mov  ecx,(LENGTHOF array) - 1

L1:	push ecx						; save loop counter
	mov  eax,[esi   TYPE DWORD]
	mov  cl,bl						; shift count
	shrd [esi],eax,cl				; shift EAX into high bits of [esi]
	add  esi,TYPE DWORD				; point to next doubleword pair
	pop  ecx						; restore loop counter
	loop L1

									; Right-shift the last doubleword
	shr DWORD PTR [esi],COUNT

	ret
ShiftDoublewords ENDP

END main
学新通

15.MultiShift

; Multiple Doubleword Shift            (MultiShf.asm)

; This program demonstrates a multibyte shift operation, 
; using SHR and RCR instructions.

INCLUDE Irvine32.inc

.data
	ArraySize		=		3
	array			BYTE	ArraySize DUP(99h)		; 1001 pattern in each nybble

.code
main PROC
	call			DisplayArray					; display the array
	
	mov				esi,0
	shr				array[esi 2],1     				; high byte 最后一个字节不需要高位上的CF标志位的值
	rcr				array[esi 1],1     				; middle byte, include Carry flag
	rcr				array[esi],1     				; low byte, include Carry flag

	call			DisplayArray					; display the array
	exit
main ENDP

;----------------------------------------------------
DisplayArray PROC
; Display the bytes from highest to lowest
;----------------------------------------------------
	pushad

		mov			ecx,ArraySize
		mov			esi,ArraySize-1
	L1:
		mov			al,array[esi]
		mov			ebx,1					; size = byte
		call		WriteBinB				; display binary bits
		mov			al,' '
		call		WriteChar
		sub			esi,1
		Loop		L1
	
		call		Crlf

	popad
	ret
DisplayArray ENDP

END main
学新通

16.使用位移操作进行乘法的简单实例

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		;本程序实现123*36
		mov eax,123
		mov ebx,eax
		shl	eax,5	;乘以2^5
		shl ebx,2	;乘以2^2
		add	eax,ebx
		call WriteInt

		invoke ExitProcess,0
	main ENDP
END main
学新通

17.显示二进制位

; Displaying Binary Bits                (WriteBin.asm)

; This program displays a 32-bit integer in binary.

INCLUDE Irvine32.inc

.data
	binValue	DWORD		1234ABCDh	; sample binary value
	buffer		BYTE		32 dup(0),0

.code
	main PROC

			mov	eax,binValue			; number to display
			mov	ecx,32					; number of bits in EAX
			mov	esi,offset buffer
			;------------------------------------------------------------
		L1:	shl	eax,1					; shift high bit into Carry flag
			mov	BYTE PTR [esi],'0'		; choose 0 as default digit
			jnc	L2						; if no Carry, jump to L2  这句话的意思是如果CF为0,那么刚才的第一位就是0
			mov	BYTE PTR [esi],'1'		; else move 1 to buffer

		L2:	inc  esi					; next buffer position
			loop L1						; shift another bit to left
			;------------------------------------------------------------
			mov  edx,OFFSET buffer		; display the buffer
			call WriteString
			call Crlf
			exit
	main ENDP
END main
学新通

18.使用MUL指令


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	WORD	2000h
	val2	WORD	0100h

.code
	main PROC

		;乘积的高半部分等于零
		mov al,5h
		mov bl,10h
		mul bl				;AX=0050h  CF=0

		;乘积的高半部分不为零
		mov ax,val1			;AX=2000h
		mul val2			;DX=0020h AX=0000h CF=1

		;产生64bit乘积的情况
		mov eax,12345h
		mov ebx,1000h
		mul ebx				;EDX=00000000h EAX=12345000h CF=0

		invoke ExitProcess,0
	main ENDP
END main
学新通

19.单操作数IMUL实例


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov al,48
		mov bl,4
		imul bl		;AX=00C0h	OF=1 由于ah不是al的符号扩展所以这里会导致OF置一

		mov al,-4
		mov bl,4
		imul bl		;AX=FFF0h  -16的补码	OF=0 由于ah是al的符号扩展因此溢出标志位清零

		mov ax,48
		mov bx,4
		imul bx		;DX:AX=0000 00C0h	OF=0 由于DX是AX的符号扩展因此溢出标志位清零

		mov eax, 4823424
		mov ebx,-423
		imul ebx	;EDX:EAX=FFFFFFFF86635D80h

		invoke ExitProcess,0
	main ENDP
END main
学新通

20.双操作数格式下的乘法


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	word1	SWORD	4
	dword1	SDWORD	4

.code
	main PROC
		
		mov ax,-16		;AX=-16
		mov bx,2		;BX=2
		imul bx,ax		;BX=-32
		imul bx,2		;BX=-64
		imul bx,word1	;BX=-256

		mov eax,-16		;EAX=-16
		mov ebx,2		;EBX=2
		imul ebx,eax	;EBX=-32
		imul ebx,2		;EBX=-64
		imul ebx,dword1	;EBX=-256

		invoke ExitProcess,0
	main ENDP
END main
学新通

21.三操作数格式的乘法


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	word1	SWORD	4
	dword1	SDWORD	4

.code
	main PROC
		
		imul	bx,word1,-16			;BX=word1*-16=-64		FFFFFFFFFFFFFFC0
		imul    ebx,dword1,-16			;EBX=dword1*-16=-64		FFFFFFFFFFFFFFC0
		imul    ebx,dword1,-200000000	;有符号溢出

		invoke ExitProcess,0
	main ENDP
END main
学新通

22.CompareMult

; Comparing Multiplications         (CompareMult.asm)

; This program compares the execution times of two approaches to 
; integer multiplication: Binary shifting versus the MUL instruction.

INCLUDE Irvine32.inc

LOOP_COUNT = 0FFFFFFFFh

.data
intval DWORD 5
startTime DWORD ?

.code
main PROC

; First approach:

	call	GetMseconds	; get start time
	mov	startTime,eax
	
	mov	eax,intval	; multiply now
	call	mult_by_shifting
	
	call	GetMseconds	; get stop time
	sub	eax,startTime
	call	WriteDec		; display elapsed time
	call	Crlf

; Second approach:

	call	GetMseconds	; get start time
	mov	startTime,eax
	
	mov	eax,intval
	call	mult_by_MUL

	call	GetMseconds	; get stop time
	sub	eax,startTime
	call	WriteDec		; display elapsed time
	call	Crlf

	exit
main ENDP


;---------------------------------
mult_by_shifting PROC
;
; Multiplies EAX by 36 using SHL
;    LOOP_COUNT times.
; Receives: EAX
;---------------------------------

	mov	ecx,LOOP_COUNT
	
L1:	push	eax			; save original EAX
	mov	ebx,eax
	shl	eax,5
	shl	ebx,2
	add	eax,ebx
	pop	eax			; restore EAX
	loop	L1
	
	ret
mult_by_shifting ENDP


;---------------------------------
mult_by_MUL PROC
;
; Multiplies EAX by 36 using MUL
;    LOOP_COUNT times.
; Receives: EAX
;---------------------------------

	mov	ecx,LOOP_COUNT
	
L1:	push	eax			; save original EAX
	mov	ebx,36
	mul	ebx
	pop	eax			; restore EAX
	loop	L1
	
	ret
mult_by_MUL ENDP

END main
学新通

23.无符号模式下的DIV实例


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	dividend	QWORD	0000000800300020h
	divisor		DWORD	00000100h

.code
	main PROC

		;八位无符号出发
		mov ax,0083h	;被除数
		mov bl,2		;除数
		div bl			;AL=41h,AH=01h
		;十六位无符号除法
		mov dx,0		;清除被除数高16位
		mov ax,8003h	;被除数的低十六位
		mov cx,100h		;除数
		div cx			;AX=0080h DX=0003h
		;三十二位无符号除法
		mov edx,DWORD PTR dividend 4	;高双字
		mov eax,DWORD PTR dividend		;低双字
		div divisor						;EAX=08003000h	EDX=00000020h

		invoke ExitProcess,0
	main ENDP
END main
学新通

24.有符号除法的符号扩展01


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	wordVal		SWORD	 -101
	
.code
	main PROC
		mov dx,0
		mov ax,wordVal
		cwd					;将正确的符号位扩展到dx中
		mov bx,2
		idiv bx				;-101/2=-50...-1
							;AX=-50 DX=-1
		invoke ExitProcess,0
	main ENDP
END main
学新通

25.符号扩展指令


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	byteVal		SBYTE	-101		
	wordVal		SWORD	-101
	dwordVal	DWORD	-101

.code
	main PROC
		
		mov al,byteVal
		cbw					;AX=ff9b

		mov ax,wordVal	
		cwd					;DX:AX=ffff ff9b

		mov eax,dwordVal
		cdq					;EDX:EAX=ffff ffff ffff ff9b

		invoke ExitProcess,0
	main ENDP
END main
学新通

26.IDIV指令


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	byteVal		SBYTE	-48
	wordVal		SWORD	-5000
	dwordVal	SDWORD	 50000

.code
	main PROC
		
		mov al,byteVal	;被除数的低字节
		cbw				;AL扩展到AH
		mov bl, 5		;除数
		idiv bl			;AL=-9 AH=-3

		mov ax,wordVal	;被除数的低字节
		cwd				;AX扩展到DX
		mov bx, 256		;除数
		idiv bx			;AX=-19 DX=-136

		mov eax,dwordVal;被除数的低双字
		cdq				;EAX扩展到EDX
		mov ebx,-256	;除数
		idiv ebx		;EAX=-195 EDX= 80


		invoke ExitProcess,0
	main ENDP
END main
学新通

27.实现算术运算表达式反汇编01

#include<iostream>

using namespace std;

int main()
{
	int var4, var1, var2, var3;
	var1 = 1;
	var2 = 2;
	var3 = 3;
	var4 = 4;

	var4 = (var1   var2) * var3;

	system("pause");
	return 0;
}
学新通

28.实现算术运算表达式反汇编02

#include<iostream>

using namespace std;

int main()
{
	int var4, var1, var2, var3,var5;
	var1 = 1;
	var2 = 2;
	var3 = 3;
	var4 = 4;
	var5 = 5;

	var4 = (var1 * 5) / (var2-3);

	system("pause");
	return 0;
}
学新通

29.实现算术运算表达式反汇编03

#include<iostream>

using namespace std;

int main()
{
	int var4, var1, var2, var3;
	var1 = 1;
	var2 = 2;
	var3 = 3;
	var4 = 4;

	var4 = (var1 * -5) * (-var2 % var3);

	system("pause");
	return 0;
}
学新通

30.ADC指令的使用实例


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov dl,0
		mov al,0FFh
		add al,0FFh	;AL=FEh
		adc dl,0	;DL=01h   RES=DL/AL=01FEh

		invoke ExitProcess,0
	main ENDP
END main
学新通

31.ADC指令的使用实例


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov edx,0
		mov eax,0FFFFFFFh
		add eax,0FFFFFFFh
		adc edx,0			;进位值存储在EDX中,加法的结果为 EDX/EAX=00000001/fffffffe

		invoke ExitProcess,0
	main ENDP
END main
学新通

32.ExtendAddProc

; Extended Addition Example           (ExtAdd.asm)

; This program calculates the sum of two 8-byte integers.
; The integers are stored as arrays, with the least significant 
; byte stored at the lowest address value.

INCLUDE Irvine32.inc

.data
	op1 BYTE 34h,12h,98h,74h,06h,0A4h,0B2h,0A2h
	op2 BYTE 02h,45h,23h,00h,00h,87h,10h,80h

	sum BYTE 9 dup(0) 	; = 0122C32B0674BB5736h

.code
	main PROC

		mov	esi,OFFSET op1		; first operand
		mov	edi,OFFSET op2		; second operand
		mov	ebx,OFFSET sum		; sum operand
		mov	ecx,LENGTHOF op1   	; number of bytes
		call	Extended_Add

	; Display the sum.
	
		mov  esi,OFFSET sum
		mov  ecx,LENGTHOF sum
		call	Display_Sum
		call Crlf
	
		exit
	main ENDP

	;--------------------------------------------------------
	Extended_Add PROC
	;
	; Calculates the sum of two extended integers stored 
	; as arrays of bytes.
	; Receives: ESI and EDI point to the two integers,
	; EBX points to a variable that will hold the sum, and
	; ECX indicates the number of bytes to be added.
	; Storage for the sum must be one byte longer than the
	; input operands.
	; Returns: nothing
	;--------------------------------------------------------
		pushad
			clc                			; clear the Carry flag

		L1:	
			mov	al,[esi]      			; get the first integer
			adc	al,[edi]      			; add the second integer
			pushfd              		; save the Carry flag
			mov	[ebx],al      			; store partial sum
			add	esi,1         			; advance all 3 pointers
			add	edi,1
			add	ebx,1
			popfd               		; restore the Carry flag
			loop	L1           			; repeat the loop

			mov	byte ptr [ebx],0		; clear high byte of sum
			adc	byte ptr [ebx],0		; add any leftover carry
			popad
		ret
	Extended_Add ENDP

	;-----------------------------------------------------------
	Display_Sum PROC
	;
	; Displays a large integer that is stored in little endian 
	; order (LSB to MSB). The output displays the array in 
	; hexadecimal, starting with the most significant byte.
	; Receives: ESI points to the array, ECX is the array size
	; Returns: nothing
	;-----------------------------------------------------------
			pushad
	
				; point to the last array element
				add esi,ecx
				sub esi,TYPE BYTE
				mov ebx,TYPE BYTE
	
			L1:	mov  al,[esi]			; get an array byte
				call WriteHexB			; display it
				sub  esi,TYPE BYTE		; point to previous byte
				loop L1

			popad
		ret
	Display_Sum ENDP


END main
学新通

33.SBB指令的应用


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		mov edx,7	;高32位
		mov eax,1	;低32位
		sub eax,2	;减去2 00000007 00000001 - 00000000 00000002 = 00000006 FFFFFFFF  CF=1 由于是减法这里的CF要被edx减去
		sbb edx,0	;高32位减法 先进行减法操作,然后在进行借位操作

		invoke ExitProcess,0
	main ENDP
END main
学新通

34.AAA指令实现多字节加法

include irvine32.inc

DECIMAL_OFFSET = 5							;距离串右侧的偏移量

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	decimal_one		BYTE	"100123456789765"				;1001234567.89765
	decimal_two		BYTE	"900402076502015"				;9004020765.02015
	sum				BYTE	(SIZEOF decimal_one 1) DUP(0),0

.code
	main PROC

		;从最后一个数字位开始
		mov		esi,sizeof decimal_one - 1
		mov		edi,sizeof decimal_one
		mov		ecx,sizeof decimal_one
		mov		bh ,0											;进位值清零

	L1:
		mov		ah,0											;执行加法前清除AH
		mov		al,decimal_one[esi]								;取第一个数字
		add		al,bh											;加上之前的进位值
		aaa														;调整合数ah=进位值
		mov		bh,ah											;将进位保存到carry1
		or		bh,30h											;将其转化为ASCII码
		add		al,decimal_two[esi]								;加第二个数字
		aaa														;调整合数ah=进位值
		or		bh,ah											;进位值与carry1进行OR运算?
		or		bh,30h											;将其转换为ASCII码
		or		al,30h											;将AL转化为ASCII码
		mov		sum[edi],al										;将AL保存到SUM
		dec		esi												;后退一个数字
		dec		edi
		loop	L1
		mov		sum[edi],bh										;保存最后的进位值

		;显示和数字符串
		mov		edx,offset sum
		call	WriteString
		call	Crlf

		invoke ExitProcess,0
	main ENDP
END main
学新通

35.AddPacked

; Packed Decimal Examples            (AddPacked.asm)

; This program adds two decimal integers.

INCLUDE Irvine32.inc

.data
	packed_1 WORD 4536h
	packed_2 WORD 7207h
	sum DWORD ?

.code
	main PROC
	; Initialize sum and index.
		mov	sum,0
		mov	esi,0
	
	; Add low bytes.
		mov	al,BYTE PTR packed_1[esi]
		add	al,BYTE PTR packed_2[esi]
		daa
		mov	BYTE PTR sum[esi],al
	
	; Add high bytes, include carry.
		inc	esi
		mov	al,BYTE PTR packed_1[esi]
		adc	al,BYTE PTR packed_2[esi]
		daa
		mov	BYTE PTR sum[esi],al

	; Add final carry, if any.
		inc	esi
		mov	al,0
		adc	al,0
		mov	BYTE PTR sum[esi],al
	
	; Display the sum in hexadecimal.	
		mov	eax,sum
		call	WriteHex
		call	Crlf
		exit
	main ENDP
END main
学新通

习题

7.01.10 05


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		mov ax,1111h
		mov bx,0000h
		shrd bx,ax,1			;dest source count


		invoke ExitProcess,0
	main ENDP
END main
学新通

7.01.10 06

include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		mov eax,10
		
		mov	ecx,32		;循环计数器
		mov  bl,0		;计算1的个数
	L1:
		shr	eax,1		;移位到进位标志位
		jnc	L2			;进位标志位置一?
		inc bl			;是:进位计数器加一
	L2:
		loop L1			;继续循环
		;若BL为奇数,清除奇偶标志位
		;若BL为偶数,奇偶标志位置一
			shr		bl,1
			jc		odd
			mov		bh,0
			or		bh,0;PF=1
			jmp		next
	odd:
		mov	bh,1		
		or  bh,1		;PF=0

	next:
					
		call WaitMsg
	main ENDP
END main
学新通

7.02.05.01


include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov eax,5
		mov ebx,eax
		mov ecx,eax
		shl ebx,4
		shl ecx,3
		add ebx,ecx
		mov eax,ebx

		call WriteInt
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.02.05.02


include irvine32.inc

.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov eax,5
		
		mov ebx,eax
		mov ecx,eax
		mov edx,eax
		
		shl ebx,4
		shl ecx,2
		shl edx,0

		mov eax,0

		add eax,ebx
		add eax,ecx
		add eax,edx


		call WriteInt
		call WaitMsg

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.02.05.03

; Displaying Binary Bits                (WriteBin.asm)

; This program displays a 32-bit integer in binary.

INCLUDE Irvine32.inc

.data
	binValue	DWORD		1234ABCDh	; sample binary value
	buffer		BYTE		32 dup(0)
	temp		BYTE		32 dup(0)

.code
	main PROC

			mov	eax,binValue			; number to display
			mov	ecx,32					; number of bits in EAX
			mov	esi,offset buffer
			;------------------------------------------------------------
		L1:	shl	eax,1					; shift high bit into Carry flag
			mov	BYTE PTR [esi],'0'		; choose 0 as default digit
			jnc	L2						; if no Carry, jump to L2  这句话的意思是如果CF为0,那么刚才的第一位就是0
			mov	BYTE PTR [esi],'1'		; else move 1 to buffer

		L2:	inc  esi					; next buffer position
			loop L1						; shift another bit to left
			;------------------------------------------------------------
			mov  edx,OFFSET buffer		; display the buffer
			call WriteString
			call Crlf

			call reverse
			mov  edx,OFFSET buffer		; display the buffer
			call WriteString

			exit
	main ENDP

	;定义一个过程将buffer里面的字节全部逆序
	reverse PROC
		pushad
			;思路 使用栈
			mov esi,0
			mov ecx,lengthof buffer
			L:
				movzx eax,buffer[esi]
				inc esi
				push eax
				loop L
	
			mov esi,0
			mov ecx,lengthof buffer
			U:
				pop eax
				mov buffer[esi],al
				inc esi

				loop U
		popad
		ret
	reverse ENDP

END main
学新通

7.02.05.04


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	bMinutes BYTE 0

.code
	main PROC

		mov dx,0000000001100011b
		shr dx,5
		and dl,00111111b
		mov bMinutes,dl

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.04.04.03


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov edx,10h
		mov eax,0A0000000h
		add eax,20000000h
		adc edx,0
		invoke ExitProcess,0
	main ENDP
END main
学新通

7.04.04.04


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov edx,100h
		mov eax,80000000h
		sub eax,90000000h
		sbb edx,0			;向高位借位
		;edx=0x000000ff
		;eax=0xf0000000
		invoke ExitProcess,0
	main ENDP
END main
学新通

7.04.04.05


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov dx,5
		stc
		mov ax,10h
		adc dx,ax		;dx=16
		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.01.01


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov al,0D4h
		shr al,1		;06ah
		mov al,0D4h
		sar	al,1		;0xea
		mov al,0D4h
		sar al,4		;0xfd
		mov al,0D4h
		rol al,1		;0xa9
		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.01.02


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov al,0D4h
		ror al,3
		mov al,0D4h
		rol al,7
		stc
		mov al,0D4h
		rcl al,1
		stc
		mov al,0D4h
		rcr al,3

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.01.03~07


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		;03
		mov dx,0
		mov ax,222h
		mov cx,100h
		mul cx

		;04
		mov ax,63h
		mov bl,10h
		div bl

		;05
		mov eax,123400h
		mov edx,0
		mov ebx,10h
		div ebx

		;06
		;mov ax,4000h
		;mov dx,500h
		;mov bx,10h
		;div bx

		;07
		mov bx,5
		stc
		mov ax,60h
		adc bx,ax

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.01


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
	
		shl eax,16
		sar eax,16

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.02


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		shr al,1		; shift AL into Carry flag
		jnc next		; Carry flag set?
		or al,80h		; yes: set highest bit
		next:			; no: do nothing
		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.03


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov eax,1
		shl eax,4

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.04


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC
		
		mov eax,16
		shr eax,2

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.05


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov dl,11110000b
		ror dl,4

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.06


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov ax,01111110b
		mov dx,11111111b
		shld dx,ax,1

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.07


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	byteArray	byte	81h,20h,33h

.code
	main PROC
		
		shr byteArray 2,1
		rcr byteArray 1,1
		rcr byteArray,1

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.08


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	wordArray WORD 810Dh,0C064h,93ABh

.code
	main PROC
	
		shl wordArray,1		;正常右移位,不进行循环右移操作
		rcl wordArray 2,1	;带上前一个右移过的进位CF
		rcl wordArray 4,1

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.09


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	sdword	0

.code
	main PROC
		
		mov eax,-5
		mov ebx,3
		imul eax,ebx
		mov val1,eax

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.10


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	SWORD	0
.code
	main PROC
		mov ax,-276
		cwd
		mov bx,10
		idiv bx
		mov val1,ax		;将求得的商存储在val1中,由于定义val1的时候是SWORD形式,所以在显示的时候也以SWORD的方式显示

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.11


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data

	val1	DWORD	1
	val2	DWORD	2
	val3	DWORD	5
	val4	DWORD	4

.code
	main PROC
		
		mov eax,val1
		mul val2
		mov ebx,val3
		sub ebx,3
		div ebx

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.12


.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data
	
	val1	SDWORD	1
	val2	SDWORD	3
	val3	SDWORD	2
	val4	SDWORD	4

.code
	main PROC
		
		mov eax,val2
		cdq
		idiv val3
		;EAX 商 EDX 余数
		mov ebx,val1
		mov ecx,val2
		add ebx,ecx
		mul ebx
		mov val1,eax

		invoke ExitProcess,0
	main ENDP
END main
学新通

7.09.02.13


include irvine32.inc
.686p


.model flat,stdcall


.stack 4096


	ExitProcess PROTO,dwExitCode:DWORD


.data


.code
	main PROC

		mov al,65
		call out16
		call WaitMsg

		invoke ExitProcess,0
	main ENDP

	out16 proc
		aam
		or ax,3030h
		push eax
		mov al,ah
		call WriteChar
		pop eax
		call WriteChar
		ret
	out16 endp

END main
学新通

7.10.01

; Chapter 7 Exercise 1: Display ASCII Decimal

COMMENT !
Write a procedure named WriteScaled that outputs a decimal ASCII number 
with an implied decimal point. Suppose the following number were defined 
as follows, where DECIMAL_OFFSET indicates that the decimal point must be 
inserted five positions from the right side of the number:

DECIMAL_OFFSET = 5
.data
decimal_one BYTE "100123456789765"

WriteScaled would display the number like this: 1001234567.89765

When calling WriteScaled, pass the number抯 offset in EDX, the number length 
in ECX, and the decimal offset in EBX. Write a test program that displays 
three numbers of different sizes.
!

INCLUDE Irvine32.inc

.data
one   BYTE "100123456789765"
two   BYTE "97650288015"
three BYTE "9723287725555342222"

.code
main PROC

	mov	edx,OFFSET one
	mov	ebx,5			; decimal offset
	mov	ecx,SIZEOF one
	call	WriteScaled 
	call	Crlf
 
	mov	edx,OFFSET two
	mov	ebx,3			; decimal offset
	mov	ecx,SIZEOF two
	call	WriteScaled 
	call	Crlf

	mov	edx,OFFSET three
	mov	ebx,7			; decimal offset
	mov	ecx,SIZEOF three
	call	WriteScaled 
	call	Crlf

	ret
main ENDP

;------------------------------------------------------
WriteScaled PROC uses eax ecx edx
;
; Writes a scaled ASCII decimal number to the console,
;    displaying leading zeros.
; Receives: EDX = offset of ASCII digit string, 
;    EBX = decimal offset (from right), ECX = length
; Returns: nothing
;------------------------------------------------------

	inc	ebx            ; adjust EBX for loop counter

L1:	mov	al,[edx]	
	call	WriteChar
	.IF ecx == ebx
	mov	al,'.'
	call	WriteChar
	.ENDIF
	inc	edx
	loop	L1

	ret
WriteScaled ENDP

END main
学新通

7.10.02

; Chapter 7 Exercise 2: Extended Subtraction

Comment !
Description: Create and test a procedure named Extended_Sub that
subtracts two binary integers of arbitrary size. Restrictions: The
storage size of the two integers must be the same, and their size
must be a multiple of 32 bits.
!

INCLUDE Irvine32.inc

.data
op1 QWORD 0A2B2A40674981234h
op2 QWORD 08010870000234502h
result QWORD 1 DUP(0)			; = 22A21D067474CD32h

msg BYTE "The difference equals ",0

; Count the number of doublewords in each operand.
DoubleWords = SIZEOF op1 / TYPE DWORD

.code
main PROC

	mov  esi, OFFSET op1		; first operand
	mov  edi, OFFSET op2		; second operand
	mov  ebx, OFFSET result		; result
	mov  ecx, DoubleWords		; number of doublewords
	call Extended_Sub

	mov	edx, OFFSET msg		; message to display
	call WriteString

	mov	esi, OFFSET result		; starting address of result
	add	esi, DoubleWords * 4	; move to end of last dword in result
	mov	ecx, DoubleWords		; number of doublewords

L1:	sub	esi, TYPE DWORD		; previous dword (little endian order)
	mov	eax, [esi]			; get 32 bits of result
	call WriteHex				; display on the screen
	loop L1

	call Crlf
	exit
main ENDP

;--------------------------------------------------------
Extended_Sub PROC
;
; Subtracts two binary integers whose size is a multiple
; of 32-bits.
; Receives: ESI and EDI point to the two integers,
; 	EBX points to a variable that will hold the result, and
; 	ECX indicates the size of operands (multiple of 32 bits).
; Returns: nothing
;--------------------------------------------------------
	pushad
	clc					; clear the Carry flag

L1:	mov	eax,[esi]			; get the first integer
	sbb	eax,[edi]			; subtract the second integer
	pushfd				; save the Carry flag
	mov	[ebx],eax			; store partial result
	add	esi,4			; advance all 3 pointers
	add	edi,4
	add	ebx,4
	popfd				; restore the Carry flag
	loop L1				; repeat the loop

	sbb	word ptr [ebx],0	; subtract any leftover carry
	popad
	ret
Extended_Sub ENDP

END main
学新通

7.10.03

 ;Chapter 7 Exercise 3: Packed Decimal Conversion

Comment !
Description: Write a procedure named PackedToAsc that converts a
4-byte packed decimal number to a string of ASCII decimal digits.
Pass the packed number to the procedure in EAX, and pass a pointer
to a buffer that will hold the ASCII digits. Write a short test
program that demonstrates several conversions and displays the
converted numbers on the screen.
!

INCLUDE Irvine32.inc

.data
numbers DWORD 87654321h, 45346894h, 00193492h
buffer BYTE 9 DUP(0)			; 8 digits plus null character

.code
main PROC

	mov	esi, OFFSET numbers
	mov	ecx, LENGTHOF numbers	; counter
L1:
	mov	eax, [esi]			; packed decimal number
	mov	edx, OFFSET buffer		; pointer to buffer
	call PackedToAsc			; convert to ASCII digits
	call WriteString			; display string of digits
	call Crlf

	add	esi, TYPE numbers		; next number
	loop L1

	exit

main ENDP

;----------------------------------------------------------------
PackedToAsc PROC
;
; procedure that converts a 4-byte packed decimal number
; to a string of ASCII decimal digits
; Receives: EAX = packed decimal number
; Returns: String of ASCII digits in buffer pointed by EDX
;------------------------------------------------------------------

	pushad			; save general registers to stack

	mov	ecx,8		; 8 decimals digits (2 digits per byte)
L1:
	mov	ebx,eax		; make a copy of number
	and	ebx,0F0000000h	; keep 4 highest bits (one decimal digit)
	rol	ebx,4		; move to the lower 4 positions
	or	bl,30h		; convert digit to ASCII character
	mov	[edx],bl		; save to buffer

	inc	edx			; next byte in buffer
	shl	eax,4		; discard highest 4 bits (already copied)
	loop L1			; next digit

	popad			; restore registers from stack
	ret

PackedToAsc ENDP

END main
学新通

7.10.04

TITLE Chapter 7 Exercise 4: Encryption Using Rotate Operations

Comment !
Description: This program performs simple encryption by rotating 
each plaintext byte a varying number of positions in different directions. 
For example, in the following array that represents the encryption key, 
a negative value indicates a rotation to the left and a positive value 
indicates a rotation to the right. The integer in each position indicates 
the magnitude of the rotation:

key BYTE -2, 4, 1, 0, -3, 5, 2, -4, -4, 6

The program loops through a plaintext message and aligns the key to 
the first 10 bytes of the message. It rotates each plaintext byte by the amount 
indicated by its matching key array value. Then, the key is aligned to the next 
10 bytes of the message and the process is repeated.
!

INCLUDE Irvine32.inc

.data
key BYTE -2, 4, 1, 0, -3, 5, 2, -4, -4, 6
keySize = $ - key
plainText BYTE "This is a secret message, which will be encrypted",0

.code
main PROC
	call Clrscr

	mov  esi,OFFSET plainText
	
L1:	mov  ecx,keySize
	mov  edi,OFFSET key
	call Encode			; encode 10 bytes
	jnz	L1				; continue if ZF not set

; Optional: decode the string by reversing the rotations	

	mov  esi,OFFSET plainText
	
L2:	mov  ecx,keySize
	mov  edi,OFFSET key
	call Decode			; decode 10 bytes
	jnz	L2				; continue if ZF not set

	mov  edx,OFFSET plainText	; display the decoded text
	call	WriteString
	call Crlf
	
	exit
main ENDP

;-----------------------------------------------------
Encode PROC
; Encode a string by rotating each byte in a different
; direction and amount.
; Receives: ECX = key length, ESI = addr of the plainText,
;           EDI = addr of the key
; Returns: ZF = 1 if the end of string was found
;-----------------------------------------------------

L1:	push ecx				; save loop count
	cmp  BYTE PTR[esi],0	; end of string?
	je	L4				; yes: quit with ZF=1

	mov	cl,[edi]			; key byte
	cmp  cl,0				; if positive, skip to L2
	jge  L2
	rol  BYTE PTR[esi],cl	; else, rotate left
	jmp	L3
L2:	ror	BYTE PTR[esi],cl	; rotate right

L3:	inc	esi				; next plaintext byte
	inc	edi				; next key byte
	pop	ecx				; restore loop count
	loop L1
	
	; Clear the zero flag to indicate that we have
	; not yet reached the end of the string.
	or	eax,1
	jmp	L5

L4:	pop	ecx				; ecx was left on the stack
L5:	ret
Encode ENDP


;-----------------------------------------------------
Decode PROC
; Decode a string by rotating each byte in a different
; direction and amount.
; Receives: ECX = key length, ESI = addr of the plainText,
;           EDI = addr of the key
; Returns: ZF = 1 if the end of string was found
;-----------------------------------------------------

L1:	push ecx				; save loop count
	cmp  BYTE PTR[esi],0	; end of string?
	je	L4				; yes: quit with ZF=1

	mov	cl,[edi]			; key byte
	cmp  cl,0				; if positive, skip to L2
	jge  L2
	ror  BYTE PTR[esi],cl	; else, rotate right
	jmp	L3
L2:	rol	BYTE PTR[esi],cl	; rotate left

L3:	inc	esi				; next plaintext byte
	inc	edi				; next key byte
	pop	ecx				; restore loop count
	loop L1
	
	; Clear the zero flag to indicate that we have
	; not yet reached the end of the string.
	or	eax,1
	jmp	L5

L4:	pop	ecx				; ecx was left on the stack
L5:	ret
Decode ENDP

END main
学新通

7.10.05

; Chapter 7 Exercise 5: Prime Numbers

Comment !
Write a program that generates all prime numbers between 2 and 1000, 
using the Sieve of Eratosthenes method. You can find many articles that 
describe the method for finding primes in this manner on the Internet. 
Display all the prime values.
!

INCLUDE Irvine32.inc

PrintPrimes PROTO,
	count:DWORD			; number of values to display

FIRST_PRIME = 2
LAST_PRIME = 2000000		; try a larger array than 65,000

.data
commaStr BYTE ", ",0

.data?
sieve BYTE LAST_PRIME DUP(?)

.code
main PROC
	; initialize the array to zeros
	mov	ecx,LAST_PRIME
	mov	edi,OFFSET sieve
	mov	al,0
	cld
	rep	stosb


	mov esi,FIRST_PRIME

	.WHILE esi < LAST_PRIME
	  .IF sieve[esi*TYPE sieve] == 0		; is current entry prime?
	    call MarkMultiples				; yes: mark all of its multiples
	  .ENDIF
	  inc esi							; move to next table entry
	.ENDW

	INVOKE PrintPrimes, LAST_PRIME		; display all primes found

	exit
main ENDP

;--------------------------------------------------
MarkMultiples PROC
;
; Mark all multiples of the value passed in ESI.
; Notice we use ESI as the prime value, and
; take advantage of the "scaling" feature of indirect
; operands to locate the address of the indexed item:
; [esi*TYPE sieve]
;--------------------------------------------------
	push eax
	push esi
	mov  eax,esi				; prime value
	add  esi,eax				; start with first multiple

L1:	cmp	esi,LAST_PRIME			; end of array?
	ja	L2					; yes
	mov	sieve[esi*TYPE sieve],1	; no: insert a marker
	add	esi,eax
	jmp	L1					; repeat the loop

L2:	pop	esi
	pop	eax
	ret
MarkMultiples ENDP


;--------------------------------------------------
PrintPrimes PROC,
	count:DWORD	; number of values to display
;
; Display the list of prime numbers
;--------------------------------------------------
	mov	esi,1
	mov	eax,0
	mov	ecx,count

L1:	mov al,sieve[esi*TYPE sieve]
	.IF al == 0
	  mov  eax,esi
	  call WriteDec
	  mov  edx,OFFSET commaStr
	  call WriteString
	.ENDIF
	inc	esi
	loop L1

	ret
PrintPrimes ENDP


END main
学新通

7.10.06

; Chapter 7 Exercise 6: Greatest Common Divisors

Comment !
Description: The greatest common divisor of two integers is the largest
integer that will evenly divide both integers. The GCD algorithm involves
integer division in a loop, described by the following C   code:

	int GCD(int x, int y)
	{
	  x = abs(x);            // absolute value
	  y = abs(y);

	  do {
	    int n = x % y;
	    x = y;
	    y = n;
	  } while y > 0;

	  return y;
	}

Implement this function in assembly language and write a test program that
calls the function several times, passing it different values. Display all
results.
!

INCLUDE Irvine32.inc

.data
array SDWORD -5,-20,18,24,11,7,438,226,13,-26
str1 BYTE "Greatest common divisor is: ",0

.code
main PROC

	mov	ecx,LENGTHOF array / 2
	mov  esi,OFFSET array

L1:	mov  eax,[esi]
	mov  ebx,[esi 4]
	call CalcGcd
	mov  edx,OFFSET str1
	call WriteString
	call WriteDec
	call Crlf
	add  esi,TYPE array * 2
	loop L1

	exit
main ENDP

;---------------------------------------------
CalcGcd PROC
;
; Calculate the greatest common divisor, using
; a nonrecursive looping algorithm.
; Receives: EAX (integer 1), EBX (integer 2)
; Returns: EAX = Greatest common divisor
;---------------------------------------------
	push ebx
	push edx

	.IF SDWORD PTR eax < 0		 ; force a signed comparison
	  neg eax	; EAX = abs(EAX)
	.ENDIF

	.IF SDWORD PTR ebx < 0
	  neg ebx	; EBX = abs(EBX)
	.ENDIF

L1:	mov  edx,0
	div  ebx				; divide int1 by int2
	cmp  edx,0			; remainder = 0?
	je   L2				; yes: quit
	mov  eax,ebx			; no: prepare for
	mov  ebx,edx			; next iteration
	jmp  L1

L2:	mov eax,ebx			; EAX = GCD

	pop edx
	pop ebx
	ret
CalcGcd ENDP

END main
学新通

7.10.07

; Chapter 7 Exercise 5: Bitwise Multiplication

Comment !
Solution, version 1:
Description: Write a procedure named BitwiseMultiply that multiplies any
unsigned 32-bit integer by EAX, using only shifting and addition. Pass
the integer to the procedure in the EBX register, and return the product
in the EAX register. Write a short test program that calls the procedure
and displays the product. (We will assume that the product is never
larger than 32 bits.)
!

INCLUDE Irvine32.inc
.data
str1 BYTE "Bitwise Multiplication of Unsigned",
	     " Integers",0dh,0ah,0dh,0ah,0
p1 BYTE "Enter the  multiplicand: ",0
p2 BYTE "Enter the  multiplier: ",0
p3 BYTE "The product is ",0
				 
.code
main PROC
	call Clrscr
	mov  edx,OFFSET str1	; program title
	call WriteString

; Input the multiplicand
	mov	edx,OFFSET p1
	call WriteString
	call ReadDec
	mov	ebx,eax

; Input the multiplier
	mov	edx,OFFSET p2
	call	WriteString
	call ReadDec
	call Crlf

	; multiply EBX by EAX, producing EAX
	call Multiply

	; Display the product in EAX
	mov	edx,OFFSET p3
	call	WriteString
	call WriteDec
	call Crlf
	
	exit
main ENDP

;-----------------------------------------------------------------
Multiply PROC uses ecx edx esi
;
; Multiplies EBX by EAX, using shifting and addition.
; Receives: EBX = multiplicand, EAX = multiplier
; Returns: EAX = product
;----------------------------------------------------------------
	mov	edx,eax			; make a copy of multiplier
	mov	eax,0			; clear accumulator
	mov	cl,0				; initialize bit position counter

L1:	shr	edx,1			; low bit set?
	jnc	L2				; no: skip this bit position

	mov	esi,ebx			; yes: make copy of multiplicand
	shl  esi,cl			; shift it left, using shift counter
	add	eax,esi			; add partial product to accumulator

L2:	inc	cl				; next bit position
	cmp	cl,32			; end of loop?
	jb	L1				; no: multiply next bit

L3:	ret
Multiply ENDP

END main
学新通

7.10.08

; Chapter 7 Exercise 8: Add Packed Integers

COMMENT !
Description: Using the code in Section 7.7.1, write a procedure 
named AddPacked that adds two packed decimal integers of equal 
size. Write a test program that passes AddPacked several pairs 
of integers: 4-byte, 8-byte, and 16-byte. Display the sums in 
hexadecimal.
!

INCLUDE Irvine32.inc

.data
packed_1a WORD 4536h
packed_1b WORD 7207h
sum_1 DWORD ?

packed_2a DWORD 67345620h
packed_2b DWORD 54496342h
sum_2 DWORD 2 DUP(?)

packed_3a QWORD 6734562000346521h
packed_3b QWORD 5449634205738261h
sum_3 DWORD 3 DUP(?)

.code
main PROC

; Test first pair of values.
	mov	sum_1,0			; caller must initialize sum

	mov	esi,OFFSET packed_1a
	mov	edi,OFFSET packed_1b
	mov	edx,OFFSET sum_1
	mov	ecx,SIZEOF packed_1a
	call	AddPacked

	; display the sum
	mov	eax,sum_1
	call	WriteHex
	call	Crlf

; Test second pair of values.

	mov	sum_2,0			; caller must initialize sum
	mov	sum_2   4, 0
	
	mov	esi,OFFSET packed_2a
	mov	edi,OFFSET packed_2b
	mov	edx,OFFSET sum_2
	mov	ecx,SIZEOF packed_2a
	call	AddPacked
	
	; display the sum
	mov	eax,sum_2   4
	call	WriteHex
	mov	eax,sum_2
	call	WriteHex
	call	Crlf

; Test third pair of values.

; Clear the sum to zero.

	mov	ecx,3
	mov	esi,0
L1:	mov	sum_3[esi*4],0
	inc	esi
	loop	L1
	
	mov	esi,OFFSET packed_3a
	mov	edi,OFFSET packed_3b
	mov	edx,OFFSET sum_3
	mov	ecx,SIZEOF packed_3a
	call	AddPacked

	; Display the sum.	

	mov	ecx,3
	mov	esi,2
L2:	mov	eax,sum_3[esi*4]
	call	WriteHex
	dec	esi
	loop	L2

	call	Crlf

	exit
main ENDP

;-----------------------------------------------------------
AddPacked PROC
;
; Adds two packed decimal integers of arbitrary size and
; stores the sum in memory. The caller must initialize the
; sum to all zeros.
; Receives: ESI = addr first number, EDI = addr second number,
;           EDX = addr of sum, ECX = number of bytes to add
; Returns:  nothing
;------------------------------------------------------------
	pushad
	clc					; clear Carry flag

; Add  bytes, include carry.

L1:	mov	al,[esi]
	adc	al,[edi]
	daa
	mov	[edx],al

; Move to next byte.
	inc	esi
	inc	edi
	inc	edx
	loop	L1

; Add final carry, if any.
	mov	al,0
	adc	al,0
	mov	[edx],al

	popad	
	ret
AddPacked ENDP

END main
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggefgg
系列文章
更多 icon
同类精品
更多 icon
继续加载