汇编语言崩溃中的成绩平均

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