为什么我的程序只使用pos或neg数字?

问题描述 投票:1回答:1

我需要编写一个分割程序,它取两个十进制数字(它们可以是正数或负数)并以二进制代码显示答案。

程序正在运行但只有pos或neg数字。当我评论neg(在NeNegSum下,我标记它)时,它与neg数字一起使用,并且在没有评论时使用pos。我需要做什么,让它与所有数字一起工作?

include 'win32ax.inc'
include 'input.inc'

.data
    num1 dd 0 
    num2 dd 0
    mes rb 100h
    Flag db 0
.code

start:
  input_dialog
  or eax, eax
  jz exit
  mov esi, eax
  call ASCIIToNum
  cmp [Flag],1
  jne .NeNeg
  ;neg eax
  mov [Flag],0
  .NeNeg:
  mov [num1], eax

  input_dialog
  ;mov ecx, 3
  or eax, eax
  jz exit
  mov esi, eax
  call ASCIIToNum
  cmp [Flag],1
  jne .NeNeg2
  ;neg eax
  mov [Flag],0
  .NeNeg2:
  mov [num2], eax
  div [num1]
  mov ebx,2

  lea esi, [mes+50]
  cmp eax,0
  jl .NeNegSumm
  neg eax
  mov [Flag],0
  .NeNegSumm:
  ;neg eax  ;<———this neg
  call NumToASCII
  cmp [Flag],1
  jne .Cout
  dec esi
  mov byte [esi],'-'
  .Cout:
  invoke  MessageBox, HWND_DESKTOP, esi, "Div is:", MB_OK
exit:
  invoke  ExitProcess,0
.end start

.input_resources

proc ASCIIToNum 
;local sum2 dd 0
  push ebx ecx
  xor eax,eax 
  xor ebx,ebx
  mov ecx, 10
  jmp .next
.next1:
  mov [Flag],1
  ;inc esi
.next: 
  mov bl, [esi]
  inc esi
  cmp bl,'-'
  je .next1

  cmp bl, ''
  or bl,bl 
  jz .done 
  sub bl, 30h 
  mul ecx 
  add eax,ebx 
  jmp .next 
.done: 
  pop ecx ebx
  ret
endp 

proc NumToASCII
;.sum2 rb 100
  push ecx edx
  mov byte [esi], 0 
  mov  ecx,2
.divloop:
  mov  edx, 0
  div  ecx
  add  dl, 30h
  dec  esi
  mov  [esi], dl
  or  eax, eax
  jnz  .divloop
  pop edx ecx  
  ret
endp
assembly x86 division fasm
1个回答
2
投票

您正在使用DIV指令来计算num2 / num1DIV用于划分无符号数。如果您需要划分有符号数(正数和负数),请使用IDIV指令。

由于IDIV [num1]实际上执行EDX:EAX / [num1],所以不要忘记事先签署延长红利。 (cdq签名 - 将EAX扩展到EDX:EAX,即将EDX的所有位设置为EAX的符号位。)

此除法的商已经是有符号数。要决定输出“ - ”字符,只需查看EAX中数字的符号即可。

附加评论:

。将符号相关指令移动到ASCIIToNum转换例程更有意义。

。转换为二进制表示不应使用除以2(非常低效)。只需向右移动即可轻松完成此操作。

。您可以编写此代码而无需单独的Flag变量。而是保存和恢复处理器标志。

include 'win32ax.inc'
include 'input.inc'

.data
    num1 dd 0 
    num2 dd 0
    mes  rb 100h
.code

start:
  input_dialog
  test eax, eax
  jz   exit
  mov  esi, eax
  call ASCIIToNum
  mov  [num1], eax

  input_dialog
  test eax, eax
  jz   exit
  mov  esi, eax
  call ASCIIToNum
  mov  [num2], eax
  CDQ                  ;Sign-extend EAX into EDX:EAX
  IDIV  [num1]         ;Signed division of EDX:EAX by [num1]

  lea  esi, [mes+50]
  test eax, eax
  pushf
  jns  .Convert        ;Quotient was positive, no NEG needed
  neg  eax
.Convert:
  call NumToASCII
  popf
  jns  .Cout           ;Quotient was positive, no '-' needed
  dec  esi
  mov  byte [esi], '-'
.Cout:
  invoke  MessageBox, HWND_DESKTOP, esi, "Div is:", MB_OK
exit:
  invoke  ExitProcess,0
.end start

.input_resources

; Input: ESI
; Output: EAX
proc ASCIIToNum 
  push  ebx esi
  xor   eax, eax
  movzx ebx, byte [esi]
  cmp   bl, '-'
  pushf
  sete  bl             ;Number is positive, no unary '-' to skip
  add   esi, ebx
.next: 
  mov   bl, [esi]
  inc   esi
  test  bl, bl 
  jz    .done 
  sub   bl, 30h 
  imul  eax, 10
  add   eax, ebx 
  jmp   .next 
.done:
  popf
  jne   .pos           ;Number is positive, no NEG needed
  neg   eax
.pos:
  pop   esi ebx
  ret
endp 

; Input: EAX
; Output: ESI, EAX=0
proc NumToASCII
  push edx
  mov  byte [esi], 0 
.divloop:
  mov  dl, '0'
  shr  eax, 1
  adc  dl, 0
  dec  esi
  mov  [esi], dl
  test eax, eax
  jnz  .divloop
  pop  edx
  ret
endp
© www.soinside.com 2019 - 2024. All rights reserved.