【问题标题】:assembly language help code with negative numbers带有负数的汇编语言帮助代码
【发布时间】:2013-01-29 10:36:39
【问题描述】:

我这里有一小段计算器代码。我想就如何使用负数执行算术运算寻求帮助。

这是我的代码:

ASSCII_LOOP : MOV EDX , 0
                  DIV ECX 
                  OR DL , 30H       ;MAKE REMINDER ASSCII
                  MOV [ESI] , DL    ;PUT ASSCII IN ASSCII_NUM
                  DEC ESI
                  INC EBP           ;ADD ONE TO THE CHAR'S COUNTER
                  CMP EAX , 0       ;IF AX > 0 GOTO 
                  JA ASSCII_LOOP    ;ASSCII_LOOP

    CMP EDI , 0                     ;CHECK IF THAT WAS A NEGETIVE NUMBER
    JZ REST                         ;IF THATS NOT NEGETIVE GOTO REST
    MOV DL , '-'
    MOV [ESI] , DL                  ;ADD A MINES SIGN TO THE STRING
    DEC ESI
    INC EBP

REST :
    LEA EDI , ASSCII_NUM

    ;MOVE THE ASSCII CODE TO IT'S RIGHT PLCAE IN ASSCII_NUM
    ORDER_ASSCII : INC ESI
                   MOV AL , BYTE PTR [ESI] 
                   MOV BYTE PTR [EDI] , AL
                   INC EDI
                   DEC EBP
                   CMP EBP , 0
                   JA ORDER_ASSCII

    MOV CL , '$'           
    MOV BYTE PTR [EDI] , CL         ;AT LAST PUT A DOLLOR SIGN AT THE END OF ASSCII_NUM

此程序检查输入是否为负,如果为负则转到 REST。我想问以下问题:

*REST在这个程序中的作用是什么?

*我想请教一下如何开始在这个程序中编写代码来对负数进行操作。我已经知道 2' 补码的事情,我想要的是 2's 补码的代码,我只是不知道从哪里开始,如何开始。我对汇编编程真的很陌生。希望你能帮助我。

这是我尝试过的代码,但它不起作用,我将其单独放置以便更好地理解:

neg_num: 
  mov ax, data
  mov ds, ax
  mov es, ax
  mov ah, 0000h
  mov al, num
  NOT al
  mov bl, al
  adc al, 00000001B
  mov bl, al

【问题讨论】:

    标签: assembly tasm


    【解决方案1】:

    我将向您展示如何实现 2 的补码以执行简单减法的示例。我将使用我自己的通用助记符来演示如何实现这一点。然后你可以将它应用到你的汇编程序中。

    我们将遵循A-B = A + (B(1的补码) + 1)的模型

    好的,假设我们想从 A (A-B) 中减去累加器 B 的内容。

    让我们假设我们的累加器 A 值的操作数已就位 ([AccA]

    首先:从内存中取出你需要的值,并将其存储在累加器 B 中。

        MOVM   B   'Move contents of memory into Acc B   ([AccB]<-someOtherValue)
    

    第二:补B的值得到它的否定

        CMPL   B   'AccB = -B   
    

    第三:将你的 1 的补码移到某个寄存器中进行临时存储

        MOVBR R0  'Move contents of Acc B to Register 0
    

    第四:我们想将“1”加载到现在可用的累加器 B

       MOVB   #1  'Move a '1' immediately to Acc B  [AccB]<- 1
    

    第五个:我们要把AccB的内容加到RO中,我们的-B就存放在这里

       ADDB   RO    ' This takes care of the (B(complement) +1 part of our model)
                    ' The resulting value will be stored in AccB
    

    第六:最后加上AccA和AccB

       ADAB     'Mnemonic for "Add AccA to AccB, result stored in AccA"
    

    这满足了我们对 A + (B(complement) + 1) 的要求

    这都是假设您的架构不允许简单的 SUBA 或 SUBB 命令。一些处理器内置了它,但由于您正在学习它的机制,因此上述基本代码结构有望为您描绘出更好的画面。

    【讨论】:

    • 然后您可以从中创建一个小子程序来处理程序中的多个减法。
    • 这似乎有点令人困惑,但我有一些想法。无论如何,我仍然远远落后于我真正想要的东西,谢谢!
    【解决方案2】:

    你在这方面遇到了太多麻烦,scarface23! x86 不使用 1 的补码,因此该示例可能有帮助,也可能没有帮助。我们使用 2 的补码,因为它“可以正常工作”(无论如何都应该如此)。您的最新代码应该为您提供 2 的补码(adc 并不正确),但仅使用 neg al 会更容易 - 这就是它的作用。

    第一个示例的REST 部分只是将您放置在缓冲区“末尾”的字符移动到缓冲区的“开头”。如果您在正确的位置 (esi) 开始打印位置,您甚至不需要这样做。

    就在您展示之前,您执行了类似test eax, 8000h 的操作来确定该数字是否为负数。如果它是否定的,你 neg eax 并设置一个标志 (edi) 来表明我们需要一个减号。由于您始终使用 32 位数字,所以我会...

    test eax, eax
    jns is_positive
    

    仅测试第 15 位适用于 16 位数字,但您在这里使用的是 32 位寄存器/指令。混合大小的数字可能是给您带来麻烦的原因。既然你有一个非常好的(未经测试,但我看不出有什么问题)32 位数字到 ASCII 例程,请输入 32 位数字。或者,我认为如果您始终切换到 16 位寄存器,您的例程仍然可以工作。用 '$' 终止你的字符串让我知道这可能是 16 位代码。使用 32 位数字/寄存器/指令仍然可以使用,但请坚持使用一种数字大小。我想你会少一些麻烦。

    在您未显示的部分 - 从键盘获取数字 - 如果用户以减号开头,请跳过减号并设置一个标志。将 ascii 原样转换为数字,如果设置了标志,则在末尾转换为 neg ax 或 neg eax。

    mov eax, 3
    sub eax, 4
    

    现在,eax 将是负数 - 一个 2 的补码 - 只需使用它。如果您希望将其更改为正数,请“翻转”所有位(not 或 xor 全部为 1)并加 1。(这适用于正数到负数或负数到正数) 2 的补码是如何工作的,但 neg 将在一条指令中完成。

    如果您需要在保留符号的同时更改数字的大小,movsx eax, al 左右会这样做,但更容易坚持相同的大小,

    您的代码中可能存在我没有看到的严重错误,但您显示的内容对我来说看起来相当不错(mov al, RESULT +1 部分除外)。我怀疑问题出在其他地方 - 可能混合了数字大小......

    【讨论】:

    • 我已经尝试了将近 2 周来解决这个问题。我知道付出努力是值得的:收集数据、信息、建议、线索、提示,但我仍然无法做到。我还是这门语言的新手,这很难,但我真的很感兴趣学习汇编。我现在的目标是让这个计算器工作,我希望我能在截止日期前通过这个。感谢 Frank 的所有帮助,包括我过去的帖子。
    • 我希望你能给我弗兰克,你是我现在唯一的希望。干杯!
    • 我尽了最大的努力,但它从来没有为我工作过。也许我只需要向您展示整个代码,以便您更好地理解我。请参考这个链接daniweb.com/software-development/assembly/threads/447042/…。我希望你有时间检查这个,你可以指出为什么负数甚至建议和建议都不起作用的问题。请
    • 它并没有真正起作用。它尝试了一切,结果相同。负数,太难处理了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 2014-07-10
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多