汇编语言系列文章仅作为实验报告和汇编学习参考,不作为任何技术文章,还望大佬们勿喷。
1. 实验名称
熟悉汇编语言的基本指令和条件指令的使用,理解汇编程序中,如何实现高级语言中的条件语句。
2. 实验要求
编写整数求和程序;运用kip irvine库中的部分过程,并阅读分析其实现源码。
3. 实验内容
- 编写多个整数求和的程序:对用户输入的多个整数进行求和,并输出结果。
阅读然后修改附录A中的求和程序(该程序实现了3个整个求和的功能),使用一个常量决定数组的大小(即程序最大可以求和的整数个数):
ARRAY_SIZE = 20
Array DWORD ARRAY_SIZE DUP(?)
写一个过程提示用户输入需要求和的整数的个数,向promptForIntegers过程传递用户输入的数值。如果用户的输入值大于ARRAY_SIZE(判断的示例代码参见附录B),那么显示一条错误信息并退出程序。提示和错误信息可以如下例所示:
How many integers will be added? 21
The array cannot be larger than 20
精心设计程序,使得在修改了ARRAY_SIZE后,错误提示信息中的ARRAY_SIZE数目值(在上例中是20)也应自动修改。
提示:
a). 编程能力一般的同学可以分两步:- 弄懂附录A的程序。该程序实现了3个整个求和的功能。
- 找到附录A的程序需要修改的地方,以实现多个整数求和。
b). 编程能力较强的同学建议直接编写程序实现。
- 对上述程序添加功能:除显示多个整数的和外,还分别显示这些整数中正整数的和负整数的和。(区分正数与负数的示例代码参见附录B)
- (可选)阅读kip irvine库中的部分过程的源码
Irvine 32位库的源码在文件Irvine32.asm中(在Irvine32_Library_sourceCode.rar压缩包中)。
建议阅读源码的过程是:DumpMem,DumpRegs,IsDigit,Random32,RandomRange,ReadChar。
4. 实验步骤或源代码、结果
1. 实验步骤
- 编写多个整数求和的程序:对用户输入的多个整数进行求和,并输出结果。
当输入的数字个数不大于20时可以进行多个整数求和,并正确输出结果。
当输入的数字个数大于20时不可以进行多个整数求和,输出错误信息。
mov edx, OFFSET str4 ; "The array cannot be larger than "
call WriteString
mov eax, ARRAY_SIZE
call WriteInt ; 输出最大值
错误提示信息中的ARRAY_SIZE数目值也应自动修改。
- 对上述程序添加功能:除显示多个整数的和外,还分别显示这些整数中正整数的和负整数的和。
2. 实验源代码、结果
1. 源代码1
INCLUDE Irvine32.inc
ARRAY_SIZE = 20
.data
str1 BYTE "How many integers will be added? ", 0
str2 BYTE "Enter a signed integer: ", 0
str3 BYTE "The sum of the integer is: ", 0
str4 BYTE "The array cannot be larger than ", 0
str5 BYTE "The array cannot be less than 0 ", 0
array DWORD ARRAY_SIZE DUP(?)
TheArraySize SDWORD ?
.code
main PROC
call Clrscr
mov esi,OFFSET array
call GetArraySize
cmp TheArraySize, ARRAY_SIZE
jg GreaterError
cmp TheArraySize, 0
jng Less0Error
mov ecx, TheArraySize
call PromptForIntegers
call ArraySum
call DisplaySum
jmp ExitProc
GreaterError:
mov edx, OFFSET str4 ; "The array cannot be larger than "
call WriteString
mov eax, ARRAY_SIZE
call WriteInt ; 输出最大值
call Crlf
jmp ExitProc
Less0Error:
mov edx, OFFSET str5 ; "The array cannot be less than 0."
call WriteString
call Crlf
jmp ExitProc
ExitProc:
exit
main ENDP
GetArraySize PROC USES eax edx
mov edx, OFFSET str1
call WriteString
call ReadInt
call Crlf
mov TheArraySize, eax
ret
GetArraySize ENDP
;----------------------------------------------------
PromptForIntegers PROC USES ecx edx esi
;
; Prompts the user for an arbitrary number of integers
; and inserts the integers into an array.
; Receive ESI points to the array, ECX = array size
; Returns: nothing
;-----------------------------------------------------------
mov edx, OFFSET str2 ; "Enter a signed integer"
L1: call WriteString ; display a string
call ReadInt ; read
call Crlf ; go to next output line
mov [esi], eax ; store in array
add esi, TYPE DWORD ; next integer
loop L1
ret
PromptForIntegers ENDP
;----------------------------------------------------------
ArraySum PROC USES esi ecx
;
; Calculates the sum of an array of 32-bit integers.
; Receives: ESI points to the array, ECX = number
; of array elements
; Returns: EAX = sum of the array elements
;------------------------------------------------------------
mov eax, 0
L1:
add eax, [esi]
add esi, TYPE DWORD ; point to next integer
loop L1 ; repeat for array size
ret ; sum is in EAX
ArraySum ENDP
;-------------------------------------------------------------
DisplaySum PROC USES edx
;
; Displays the sum on the screen
; Receives: EAX = the sum
; Return: nothing
;-------------------------------------------------------------
mov edx, OFFSET str3 ;"The sum of the .."
call WriteString
call WriteInt ;display EAX
call Crlf
ret
DisplaySum ENDP
END main
2. 源代码2
INCLUDE Irvine32.inc
ARRAY_SIZE = 20
.data
str1 BYTE "How many integers will be added? ", 0
str2 BYTE "Enter a signed integer: ", 0
str3 BYTE "The sum of the integer is: ", 0
str4 BYTE "The array cannot be larger than ", 0
str5 BYTE "The array cannot be less than 0 ", 0
str6 BYTE "The sum of the positive integer is: ", 0
str7 BYTE "The sum of the negative integer is: ", 0
array DWORD ARRAY_SIZE DUP(?)
TheArraySize SDWORD ?
.code
main PROC
call Clrscr
mov esi,OFFSET array
call GetArraySize
cmp TheArraySize, ARRAY_SIZE
jg GreaterError
cmp TheArraySize, 0
jng Less0Error
mov ecx, TheArraySize
call PromptForIntegers
call ArraySum
call DisplaySum
jmp ExitProc
GreaterError:
mov edx, OFFSET str4 ; "The array cannot be larger than "
call WriteString
mov eax, ARRAY_SIZE
call WriteInt ; 输出最大值
call Crlf
jmp ExitProc
Less0Error:
mov edx, OFFSET str5 ; "The array cannot be less than 0."
call WriteString
call Crlf
jmp ExitProc
ExitProc:
exit
main ENDP
GetArraySize PROC USES eax edx
mov edx, OFFSET str1
call WriteString
call ReadInt
call Crlf
mov TheArraySize, eax
ret
GetArraySize ENDP
;----------------------------------------------------
PromptForIntegers PROC USES ecx edx esi
;
; Prompts the user for an arbitrary number of integers
; and inserts the integers into an array.
; Receive ESI points to the array, ECX = array size
; Returns: nothing
;-----------------------------------------------------------
mov edx, OFFSET str2 ; "Enter a signed integer"
L1: call WriteString ; display a string
call ReadInt ; read
call Crlf ; go to next output line
mov [esi], eax ; store in array
add esi, TYPE DWORD ; next integer
loop L1
ret
PromptForIntegers ENDP
;----------------------------------------------------------
ArraySum PROC USES esi ecx
;
; Calculates the sum of an array of 32-bit integers.
; Receives: ESI points to the array, ECX = number
; of array elements
; Returns: EAX = sum of the array elements
;------------------------------------------------------------
mov eax, 0
mov ebx, 0
mov edx, 0
L1: cmp [esi], edx
jnl positive_zero
add ebx, [esi]
jmp loopL1
positive_zero:
add eax, [esi]
jmp loopL1
loopL1:
add esi, TYPE DWORD ; point to next integer
loop L1 ; repeat for array size
ret ; sum is in EAX
ArraySum ENDP
;-------------------------------------------------------------
DisplaySum PROC USES edx ecx
;
; Displays the sum on the screen
; Receives: EAX = the sum
; Return: nothing
;-------------------------------------------------------------
mov ecx, eax
add eax, ebx
mov edx, OFFSET str3 ;"The sum of the .."
call WriteString
call WriteInt ;display EAX
call Crlf
mov edx, OFFSET str6 ;"The sum of the positive integers"
mov eax, ecx
call WriteString
call WriteInt ;display EAX
call Crlf
mov edx, OFFSET str7 ;"The sum of the negative integers"
mov eax, ebx
call WriteString
call WriteInt ;display EAX
call Crlf
ret
DisplaySum ENDP
END main
5. 实验结论和心得体会
- 学会了多整数求和的汇编代码;
- 学会了2个数比较大小的汇编代码,要注意有符号比较和无符号比较;
- 在实验中遇到了随机性的问题,发现是使用了被保护的eax,导致错误,将eax的值赋给一个常量后用常量去比较;
- 对于几个寄存器的用法要牢记,多写程序就可以熟练;
- 调用ReadInt时会默认读取eax寄存器的值;
- 在分别求正整数和以及负整数和时,先将数字和0比较,然后分别加到两个寄存器中,最后再将2个寄存器的值加起来就是总的和。