微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

除法的意外结果取决于我使用的是 EAX、AX 还是 AL

如何解决除法的意外结果取决于我使用的是 EAX、AX 还是 AL

好吧,我有一个有限的(只输入一位数的被加数)求和程序,它在将余数保存在堆栈中并在之后打印它们的帮助下打印求和结果。

  1 global _start
  2 section .data
  3 NEW_LINE            db  10
  4 NEW_LINE_LENGTH     equ $-NEW_LINE
  5 EXIT_SUCCESS_CODE   equ 0
  6 STDIN               equ 0
  7 STDOUT              equ 1
  8 STDERR              equ 2
  9 SYSCALL_EXIT        equ 1
 10 SYSCALL_READ        equ 3
 11 SYSCALL_WRITE       equ 4
 12 
 13 section .bss
 14 sum                 resb 4
 15 remainder           resb 4
 16 buffer              resb 120
 17 
 18 section .text
 19 print_digit: 
 20     mov eax,SYSCALL_WRITE  ; 4
 21     mov ebx,STDOUT         ; 1
 22     int 80h
 23     ret 
 24 _start: 
 25     mov esi,buffer         ; buffer adress --> ESI
 26 again:
 27     ; input number:
 28     mov eax,SYSCALL_READ   ; 3
 29     mov ebx,STDIN          ; 0
 30     mov ecx,esi            ; buffer adress --> ecx
 31     mov edx,1              ; length
 32     int 80h
 33     cmp byte [esi],0       ; EOF ?
 34     je end_input
 35     inc esi                 ; next byte of buffer memory
 36     jmp again
 37 end_input:
 38     mov esi,buffer         ; buffer adress --> ESI
 39     xor edi,edi
 40     ; EDI will hold sum:
 41 loop:
 42     cmp byte [esi],0       ; EOF ?
 43     je div_preparation      
 44     cmp byte [esi],10      ; line Feed ?
 45     je .next_digit
 46     sub byte [esi],48      ; get value of digit
 47     add edi,[esi]          ; add to summ
 48     add byte [esi],48
 49 .next_digit:
 50     inc esi                 ; next symbol(?) in buffer memory
 51     jmp loop
 52     ; EDI holds summ Now
 53 div_preparation:
 54     mov [sum],edi
 55     xor edx,edx
 56     xor eax,eax
 57     xor ebp,ebp
 58     mov al,[sum]           ; ??????????????????
 59     mov esi,10
 60 push_remainder:
 61     div esi
 62     push edx                ; push remainder
 63     xor edx,edx            
 64     inc ebp                 ; remainders counter
 65     test eax,eax           ; if the quotient equal to 0 (cmp eax,0)
 66     jne push_remainder
 67 pop_remainder:
 68     xor eax,eax
 69     test ebp,ebp           ; if remainders counter equals to 0
 70     je quit
 71     pop eax
 72     mov [remainder],eax
 73     add byte [remainder],48; get digit
 74     mov ecx,remainder
 75     mov edx,4
 76     call print_digit
 77     dec ebp
 78     jmp pop_remainder
 79 quit:

为什么我在第 58 行使用 EAXAX 寄存器时得到错误的除法结果,但使用 AL 结果是正确的?

解决方法

在这部分代码中:

 46     sub byte [esi],48      ; get value of digit
 47     add edi,[esi]          ; add to summ

看起来意图是在总和中添加一位数,但实际情况并非如此。 add edi,[esi]add edi,dword [esi] 隐含相同,因此实际上以一种有趣的方式将 4 个字符添加到总和中,尽管只打算使用底部的一个,并且其中只有一个是从 ASCII 调整的char 为其等效的数字(顺便说一下,我不太明白您为什么将它们改回 ASCII 字符,但原则上应该没问题,只是多余的)。

只使用结果的低字节有效,因为低字节永远不会被那样“污染”,多余的字符被添加到 eax 的高字节中。

如何解决:确保一次只添加一个字符。例如

movzx eax,byte [esi]
sub eax,48
add edi,eax

如果您愿意,可以将 subadd 合并到 lea 中:

movzx eax,byte [esi]
lea edi,[edi + eax - 48]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。