汇编语言崩溃中的成绩平均
Grade averaging in assembly language crashes
我正在尝试调整我们在 class 中开发的一些代码,但遇到了问题。
这是我们在 class 中开发的代码 -- 取 10 个数字,取它们的平均值。
include irvine32.inc
Title GetTen
.data
inprompt db "Enter a number:",0
sumMsg db "The sum of your numbers is ",0
avgMsg db "The average of your number is ",0
nums db 10 dup(0) ;duplicate nums 10 times for indirect
sum db 0
divisor db 0
.code
main proc
call getValues
call sumValues
call calcAvg
exit
jmp ENDITALL
;SUM 10 VALUES
sumValues proc
mov ebx,offset nums
mov ecx, lengthof nums
sub eax,eax
SumLoop:
add al,[ebx]
add ebx,1
loop SumLoop
mov sum,al
mov edx,offset sumMsg
call WriteString
call WriteInt
call crlf
ret
sumValues endp
;READ 10 Numbers in proc
getValues PROC
mov ebx, offset nums
mov ecx, lengthof nums
InLoop:
mov edx, offset inprompt
call WriteString
call ReadInt
call crlf
mov [ebx],al
add ebx,1 ;add one to advance the nums array
loop InLoop
ret
getValues endp
;--------Calculate the average
calcAvg proc
mov ebx, lengthof nums
mov divisor,bl
call dumpregs
div bl ;the first operand is always eax
;call dumpregs
mov edx, offset avgMsg
call writestring
movsx eax,al
;call dumpregs
call writeInt
ret
calcAvg endp
ENDITALL:
main endp
end main
该代码运行良好。我需要把它变成一个成绩计算器(输入十个数字成绩,取平均值,然后将平均值与一些预先设定的值进行比较以指定一个数字成绩。)所有基本的东西,除了 AL 也不喜欢像 100 这样的数字很多——如果我输入 5 个 100 和 5 个 80,它会告诉我数字的总和是 132,平均值是 13。
好的,所以我尝试用 AH 和 EAX 代替 AL,发现 AL 中没有足够的空间。这是代码。
include irvine32.inc
Title GradeAverage
.data
inprompt db "Enter a grade:",0
sumMsg db "The sum of your numbers is ",0
avgMsg db "The average of your grade is ",0
nums dd 10 dup(0) ;duplicate nums 10 times for indirect
sum dd 0
divisor dd 0
.code
main proc
call getValues
call sumValues
call calcAvg
exit
jmp ENDITALL
;SUM 10 VALUES
sumValues proc
mov ebx,offset nums
mov ecx, lengthof nums
sub eax,eax
SumLoop:
add eax,[ebx]
add ebx,1
loop SumLoop
;mov sum,eax ;I shouldn't even need this anymore since we're using all the same size.
mov edx,offset sumMsg
call WriteString
call WriteInt
call crlf
ret
sumValues endp
;READ 10 Numbers in proc
getValues PROC
mov ebx, offset nums
mov ecx, lengthof nums
InLoop:
mov edx, offset inprompt
call WriteString
call ReadInt
call crlf
mov [ebx],eax
add ebx,1 ;add one to advance the nums array
loop InLoop
ret
getValues endp
;--------Calculate the average
calcAvg proc
mov esi, lengthof nums
mov divisor,esi
call dumpregs
div esi ;the first operand is always eax
;call dumpregs
mov edx, offset avgMsg
call writestring
;movsx eax,eax
;call dumpregs
call writeInt
ret
calcAvg endp
ENDITALL:
main endp
end main
此代码崩溃。它会取数字,如果我说 100 5 次和 50 5 次,它告诉我总和是 -42041476,然后崩溃。
这可能是非常基本的东西,但我不知所措。我在这里做错了什么?
您至少有一个错误和一些概念问题。
概念:EAX是一个32位寄存器的名称;该寄存器的低 16 位称为 AX。在 AX 中,低 8 位称为 AL,高 8 位称为 AH。
概念:涉及内存的N位指令reads/writes内存中的N位。当您使用 AL 时,您将 read/write 8 位,而当您使用 EAX 时,您将 read/write 32 位。
...所以你的主求和循环有一个错误,它每次都从内存中读取 32 位:
SumLoop:
add eax,[ebx]
add ebx,1
loop SumLoop
假设您在 [EBX] 处有字节 [1,2,3,4]。第一个循环会将 1234H 添加到 EAX,后续循环是未知的,因为您正在读取的内存超出了数组的范围。崩溃可能是由于这个或完全不同的原因造成的。
如果您的数据是字节,您可以一个一个地读取它们:
xor edx, edx
SumLoop:
mov dl,[ebx]
add eax, edx
inc ebx
loop SumLoop
并且在你的平均过程中你有 div esi
但在你 div 之前你的 EDX 必须归零因为你 dividing [EDX,EAX] 64 位数字到ESI。您需要在该指令前添加 xor dx,dx
我正在尝试调整我们在 class 中开发的一些代码,但遇到了问题。
这是我们在 class 中开发的代码 -- 取 10 个数字,取它们的平均值。
include irvine32.inc
Title GetTen
.data
inprompt db "Enter a number:",0
sumMsg db "The sum of your numbers is ",0
avgMsg db "The average of your number is ",0
nums db 10 dup(0) ;duplicate nums 10 times for indirect
sum db 0
divisor db 0
.code
main proc
call getValues
call sumValues
call calcAvg
exit
jmp ENDITALL
;SUM 10 VALUES
sumValues proc
mov ebx,offset nums
mov ecx, lengthof nums
sub eax,eax
SumLoop:
add al,[ebx]
add ebx,1
loop SumLoop
mov sum,al
mov edx,offset sumMsg
call WriteString
call WriteInt
call crlf
ret
sumValues endp
;READ 10 Numbers in proc
getValues PROC
mov ebx, offset nums
mov ecx, lengthof nums
InLoop:
mov edx, offset inprompt
call WriteString
call ReadInt
call crlf
mov [ebx],al
add ebx,1 ;add one to advance the nums array
loop InLoop
ret
getValues endp
;--------Calculate the average
calcAvg proc
mov ebx, lengthof nums
mov divisor,bl
call dumpregs
div bl ;the first operand is always eax
;call dumpregs
mov edx, offset avgMsg
call writestring
movsx eax,al
;call dumpregs
call writeInt
ret
calcAvg endp
ENDITALL:
main endp
end main
该代码运行良好。我需要把它变成一个成绩计算器(输入十个数字成绩,取平均值,然后将平均值与一些预先设定的值进行比较以指定一个数字成绩。)所有基本的东西,除了 AL 也不喜欢像 100 这样的数字很多——如果我输入 5 个 100 和 5 个 80,它会告诉我数字的总和是 132,平均值是 13。
好的,所以我尝试用 AH 和 EAX 代替 AL,发现 AL 中没有足够的空间。这是代码。
include irvine32.inc
Title GradeAverage
.data
inprompt db "Enter a grade:",0
sumMsg db "The sum of your numbers is ",0
avgMsg db "The average of your grade is ",0
nums dd 10 dup(0) ;duplicate nums 10 times for indirect
sum dd 0
divisor dd 0
.code
main proc
call getValues
call sumValues
call calcAvg
exit
jmp ENDITALL
;SUM 10 VALUES
sumValues proc
mov ebx,offset nums
mov ecx, lengthof nums
sub eax,eax
SumLoop:
add eax,[ebx]
add ebx,1
loop SumLoop
;mov sum,eax ;I shouldn't even need this anymore since we're using all the same size.
mov edx,offset sumMsg
call WriteString
call WriteInt
call crlf
ret
sumValues endp
;READ 10 Numbers in proc
getValues PROC
mov ebx, offset nums
mov ecx, lengthof nums
InLoop:
mov edx, offset inprompt
call WriteString
call ReadInt
call crlf
mov [ebx],eax
add ebx,1 ;add one to advance the nums array
loop InLoop
ret
getValues endp
;--------Calculate the average
calcAvg proc
mov esi, lengthof nums
mov divisor,esi
call dumpregs
div esi ;the first operand is always eax
;call dumpregs
mov edx, offset avgMsg
call writestring
;movsx eax,eax
;call dumpregs
call writeInt
ret
calcAvg endp
ENDITALL:
main endp
end main
此代码崩溃。它会取数字,如果我说 100 5 次和 50 5 次,它告诉我总和是 -42041476,然后崩溃。
这可能是非常基本的东西,但我不知所措。我在这里做错了什么?
您至少有一个错误和一些概念问题。
概念:EAX是一个32位寄存器的名称;该寄存器的低 16 位称为 AX。在 AX 中,低 8 位称为 AL,高 8 位称为 AH。
概念:涉及内存的N位指令reads/writes内存中的N位。当您使用 AL 时,您将 read/write 8 位,而当您使用 EAX 时,您将 read/write 32 位。
...所以你的主求和循环有一个错误,它每次都从内存中读取 32 位:
SumLoop:
add eax,[ebx]
add ebx,1
loop SumLoop
假设您在 [EBX] 处有字节 [1,2,3,4]。第一个循环会将 1234H 添加到 EAX,后续循环是未知的,因为您正在读取的内存超出了数组的范围。崩溃可能是由于这个或完全不同的原因造成的。
如果您的数据是字节,您可以一个一个地读取它们:
xor edx, edx
SumLoop:
mov dl,[ebx]
add eax, edx
inc ebx
loop SumLoop
并且在你的平均过程中你有 div esi
但在你 div 之前你的 EDX 必须归零因为你 dividing [EDX,EAX] 64 位数字到ESI。您需要在该指令前添加 xor dx,dx