使用 ASCII 数字字符串时从 100 减 1 的结果不正确

问题描述 投票:0回答:1
section .bss
num: resb 3
  
section .text
global _start
_start:
 ; Read input
 mov eax, 3
 mov ebx, 0
 mov ecx, num
 mov edx, 3
 int 80h
   
  sub byte [num+2], 1
  cmp byte [num+2], 255
jne skip_borrow
   
   sub byte [num+1], 1
   cmp byte [num+1], 255
jne skip_borrow

   sub byte [num], 1

skip_borrow:
   cmp byte [num], 0
jne skip_carry
   mov byte [num+1], 9
   mov byte [num+2], 9  
skip_carry:      

 mov eax, 4
 mov ebx, 1
 mov ecx, num
 mov edx, 3
 int 80h

 mov eax, 1
 mov ebx, 0
 int 80h

代码读取三位输入号码和一位输入号码。小于 100 和大于 100 减去一位数有效。然而,从 100、200、300 中减去会给出错误的输出。例如,100 减 1 得到 10/而不是 99 或 099,200 减 1 得到 20/而不是 199。我该如何解决这个问题。

assembly x86 nasm bigint
1个回答
0
投票

例如,100 减 1 给出的是 10/,而不是 99 或 099

num处的输入由字符“1”、“0”和“0”组成。它们的 ASCII 值为 49、48 和 48。

sub byte [num+2], 1
cmp byte [num+2], 255
jne skip_borrow

因为

sub
指令从 [48,57] 范围内的数字减 1,所以您得到 [47,56] 范围内的结果。所以这永远不会产生数字 255,因此
jne skip_borrow
将始终被采用。

然后到达skip_borrow

skip_borrow:
  cmp byte [num], 0
  jne skip_carry
  mov byte [num+1], 9
  mov byte [num+2], 9  
skip_carry:

您希望这部分代码能够生成 99,但这永远不会发生,因为条件永远不会成立! num 处的第一个字节是 [48,57] 范围内的 ASCII 代码,因此永远不会为 0,因此将始终采用

jne skip_carry

以上所有结果都会产生两个未修改的字节,后跟一个递减的字节(如果是“0”,将显示“/”)。对于 1000 个可能的输入中的任何一个,都会发生这种情况。我会说这句话:“从低于 100 和高于 100 的数字中减去一位数字works。”证明您没有进行足够的测试...

解决方案

下一个代码将 3 位 ASCII 计数器递减,从“000”到“999”:

  mov  ecx, num

  dec  byte [ecx+2]
  cmp  byte [ecx+2], '0'
  jnb  done
  mov  byte [ecx+2], '9'

  dec  byte [ecx+1]
  cmp  byte [ecx+1], '0'
  jnb  done
  mov  byte [ecx+1], '9'

  dec  byte [ecx]
  cmp  byte [ecx], '0'
  jnb  done
  mov  byte [ecx], '9'

done:
  mov  edx, 3
  mov  ebx, 1
  mov  eax, 4
  int  80h

你可以把它写成循环:

  mov  eax, num+3
more:
  dec  eax
  dec  byte [eax]
  cmp  byte [eax], '0'
  jnb  done
  mov  byte [eax], '9'
  cmp  eax, num
  jne  more

done:
  mov  edx, 3
  mov  ecx, num
  mov  ebx, 1
  mov  eax, 4
  int  80h
© www.soinside.com 2019 - 2024. All rights reserved.