【问题标题】:assembly maximum value from input来自输入的装配最大值
【发布时间】:2017-10-19 06:49:27
【问题描述】:

用于输出两个用户输入数字中较大者的简单汇编程序。我无法正确输出。例如,如果我输入 45 和 55,最大值将是 55,但是当我尝试反向 55 和 45(答案应该仍然是 55)时,我得到 45。看起来这个程序只输出输入的第二个值和存储在 EAX。非常感谢任何帮助。

.586
.MODEL FLAT

INCLUDE io.h

.STACK 4096

.DATA
value1 DWORD ?
value2 DWORD ?

prompt1 BYTE "Enter the first number", 0
prompt2 BYTE "Enter the second number", 0
string BYTE 40 DUP (?)

resultLbl BYTE  "The maximum value you entered was:", 0

.CODE

_MainProc PROC      
input prompt1, string, 40       ;get user input value1
atod string                     ;convert input (ASCII) to integer
mov ebx, eax

input prompt2, string, 40   ; repeat for value2
atod string
mov value2, eax

cmp eax, ebx                ;compare user inputs

jg greater_than     ;jump conditional if value 1 is greater then value 2

    greater_than:   ;condition if greater than ouput
        dtoa value1, eax                    ;decimal to ASC for output of 
integer value stored at ebx
        output  resultLbl, value1           ;output value 1
            jmp exit                    

    less_than:  ;condition if less than ouput
        dtoa value1, eax
        output  resultLbl, value2           ;else output value 2    
            jmp exit

    exit:   ;quit jump              ;end if/else conditional

    mov eax, 0          ;clear memory
    mov ebx, 0
    ret
_MainProc ENDP
END

【问题讨论】:

  • 调试它。很可能 ebx 在函数调用中被覆盖。将其存储在内存中,而不是寄存器中
  • @SamiKuhmonen 没有寄存器受input 影响,根据以下链接:flylib.com/books/en/2.265.1.27/1 引用链接:输入宏仅更改指定目标的内存。它不会改变任何寄存器内容,包括标志寄存器。

标签: assembly x86


【解决方案1】:

问题在于指令的顺序。即使操作数 1 小于操作数 2,它唯一的区别是 jg greater_than 不会导致显式跳转到 greater_than 标签。然而,下一组指令是打印操作数 1,也就是说,执行控制将进入“内部”greater_than 标签。为什么?这是因为下一条指令dtoa value1, eax 正好在jg greater_than 之后。那么,你现在看到问题了吗?如果操作数 1 小于操作数 2,您不会阻止打印操作数 1。您的代码所做的只是确保您的程序打印 value1 以确保操作数 1 > 操作数 2。

您的代码等同于以下 C 代码:

if (op1>op2)goto gt;
gt: 
printf("%d",op1);
exit(0);

lt:
printf("%d",op2);
exit(0);

虽然您的意图是执行以下操作:

if(op1>op2){
 printf("%d",op1);
 exit(0);
}

printf("%d",op2);
exit(0);

要解决此问题,您必须更改指令的顺序,如下所示:

jg greater_than     ;jump conditional if value 1 is greater then value 2

    less_than:  ;condition if less than ouput
        dtoa value1, ebx
        output  resultLbl, value1           ;else output value 2    
            jmp exit

    greater_than:   ;condition if greater than ouput
        dtoa value1, eax                    ;decimal to ASC for output of integer value stored at eax
        output  resultLbl, value1           ;output value 1
            jmp exit

上面的代码通过显式跳转到greater_than标签来确保less_than标签内的代码在操作数1>操作数2时不会被执行。当操作数 1 less_than 中的指令在操作数 1

简而言之,条件跳转只有在满足条件时才会跳转,否则会执行序列中的下一条指令。您有责任按照正确的顺序排列您的指示。它们不同于 if...else 等高级条件构造。

更新:请注意,我的整个解决方案中只使用了value1

【讨论】:

  • 感谢您的帮助,我在 C++ 方面有一些经验,所以我理解的逻辑,是汇编中的实现似乎让我感到困惑。
  • 我怎样才能将其合并到检查 3 个数字?
【解决方案2】:

正如 Mayank Verma 所说,如果您在该指令之后立即使用“jg greater_than”跳转,即使 EAX EBX 条件执行的相同指令,您也永远不会执行跳转到 less_than。可以删除标签“less_than”。你应该写:

    CMP EAX,EBX
     JG greater_than

;less_than
   dtoa value1, eax
 output resultLbl, value2
    jmp exit

greater_than:
integer value stored at ebx
 output resultLbl, value1

exit:

但我有一个新的解决方案。那是一个优化的 MAX(A,B) 函数:

;  INPUT: EAX, EBX
; OUTPUT: EAX <- The maximum value between EAX, EBX

   CMP EAX,EBX
 CMOVL EAX,EBX

【讨论】:

    【解决方案3】:

    输入了 3 个值。这看起来可行吗?

    .586
    .MODEL FLAT
    
    INCLUDE io.h
    
    .STACK 4096
    
    .DATA
    value1 DWORD ?
    value2 DWORD ?
    value3 DWORD ?
    
    titleLbl BYTE   "MAXIMUM NUMBERS",0
    formula BYTE "Taking any THREE random user input numbers, this program can 
    determine which of those numbers is greater.",0
    
    prompt1 BYTE "Enter the first number",0
    prompt2 BYTE "Enter the second number",0
    prompt3 BYTE "Enter the third number",0
    string BYTE 40 DUP (?)
    
    resultLbl BYTE  "The maximum value you entered was:", 0
    max_value BYTE 11 DUP (?), 0
    
    .CODE
    
    _MainProc PROC  
    output titleLbl, formula
    
    input prompt1, string, 40       ;get user input value1
    atod string                     ;convert input (ASCII) to integer
    mov ebx, eax
    
    input prompt2, string, 40   ; repeat for value2
    atod string
    mov ecx, eax
    
    input prompt3, string, 40   ; repeat for value2
    atod string
    mov value3, eax
    
    cmp ebx, ecx                ;compare user inputs
    
    jg greater_than     ;jump conditional if value 2 is greater then value 3
    
    less_than:  ;condition if less than ouput
        cmp eax, ecx
    
        jg greater_than_again   ;jump conditional if 2 is greater than 1
    
        less_than_again: 
            dtoa max_value, ecx
            output  resultLbl, max_value          ;else output value 2    
            jmp exit
    
        greater_than_again:
        dtoa max_value, eax                    ;decimal to ASC for output of 
     integer value stored at eax
        output  resultLbl, max_value           ;output value 1
            jmp exit
    
    greater_than:   ;condition if greater than ouput
        cmp eax, ebx
    
        jg greater_than_again   ;jump conditional if 2 is greater than 1
    
        less_than_again2: 
            dtoa max_value, ebx
            output  resultLbl, max_value          ;else output value 2    
            jmp exit
    
        greater_than_again2:
        dtoa max_value, eax                    ;decimal to ASC for output of 
     integer value stored at eax
        output  resultLbl, max_value           ;output value 1
            jmp exit
    
        exit:   ;quit jump              ;end if/else conditional
    
        mov eax, 0          ;clear memory
        mov ebx, 0
        mov ecx, 0
        ret
     _MainProc ENDP
     END
    

    【讨论】:

    • 这应该是问题的正确答案吗?您将其发布为答案。
    • 我认为这可能是一个新问题,因为您说“这看起来可行吗?”。这不是你通常开始回答的方式。如果您已经对此进行了测试并且可以正常工作,那很好。
    • 是的,我知道,我使用了错误的链接来添加评论。下次我会更正。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    相关资源
    最近更新 更多