2

我正在尝试制作一个用负数执行算术运算的计算器。此处的此代码用于将输入的数字转换为 ASCII 值。如果输入为负数,我想修改此程序以执行 2 的补码转换,它应该会产生所需的输出。

目前这是我的计算器的流程:

-1+2=66675(应该是1)

-1-1=656745(应该是-2)

-1*-1=66757(应该是1)

有人建议我应该修改这部分代码以执行我想要的。我已经尽力了,但它不起作用。你能帮我做这个吗?哦,顺便说一句,我真的是组装新手..

CONVERT_ASSCII PROC NEAR

    MOV AH , BYTE PTR RESULT        ;MOVE FIRST TWO BYTE OF RESULT TO AX
    MOV AL , BYTE PTR RESULT + 1

    ;AT FIRST CHECK IF AX IS POSITIVE OR NEGETIVE
    TEST EAX , 8000H                    ;CHECK THE LAST BIT . IF THATS 1 THEN AX IS NEG , OTHERWISE THATS POSITIVE
    MOV EDI , 0                     ;AT FIRST SET OUR FLAG TO ZERO
    JZ EAX_POSITIVE                 ;AX IS POSITIVE
    NEG EAX                         ;CALCULATE NEGETIVE OF AX 
    MOV EDI , 1                     ;DI INDICATES THAT AX IS NEG

EAX_POSITIVE :
    MOV ECX , 10
    LEA ESI , ASSCII_NUM
    ADD ESI , 29                        ;MOVE TO THE LAST SPACE

    MOV EBP , 0                     ;THIS IS THE COUNTER OF CHARS

    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

    RET
CONVERT_ASSCII ENDP
4

1 回答 1

1

理解问题,然后应用语言。我会先用 C 语言编写它,然后再用汇编语言编写它。

你提到了 ASCII,但我没有看到你从 ascii 转换。

例如,当您说“-1+2”时,这是否意味着您的输入是那些项目的 ASCII 字符

0x2D,0x31,0x2B,0x32

您可以解析的一种方法是:

您需要将 0x2D 识别为减号操作,然后点击数字 1,即 ascii 中的 0x31。假设这些是十进制数字,然后去掉 0x30,例如 0xF。下一个字符是 +、0x2B、运算符,所以现在您可以返回并获取完整的数字 1 并将之前的运算符应用于它。但是您需要的寄存器大小是这些 8 位值还是 16 位或 32 位或 64 位?一个 8 位的 1 是 0x01,16 是 0x0001,等等,当你否定你得到 0xFF 或 0xFFFF 或 0xFFFFFFFF 等时。所以当前的操作符是一个 +,0x2B,下一个字符是 0x32 数字 2,并用 0xF 提取2.下一个字符是字符串的结尾,所以现在应用操作-1,如果8位为0xFF,加2,如果8位为0xFF+0x02 = 0x101,则为0x02,当剪裁为8位时为0x01,结果-1+ 2 = 1,然后你必须把它恢复为ascii,

"-1*-1" is 0x2D,0x30,0x2A,0x2B,0x30

当您在 0x2A 和 0x2B 一行中看到两个运算符时,问题就来了,在这种情况下,作为人类,我们知道这意味着在这两种情况下,减号都会否定后面的数字,然后执行乘法运算。

如果您支持更大的数字,也必须处理它们。

"12+34" 0x31,0x32,0x2B,0x33,0x34

0x31 是从 0x1 中去除的数字,但 0x32 也是一个数字,因此将 0x1 乘以 10,然后将从 0x32 中去除的 2 相加,得到 0xC,无论是累积该数字(十进制 12),然后是加号 0x2B,然后是其他数字的处理方式相同,将 0x33 中的 3 乘以 10,将 0x34 中的 4 相加,得到十进制 34(0x22),然后将这两个数字相加 0x0C + 0x22 = 0x2E(十进制 46)。在这种情况下,我假设所需的结果是 0x34,0x46,即“46”的 ascii 字符串。要到达那里,尽管您需要将 0x2e 除以 10,因为它大于 10,要获得第一个数字 4,余数(模 10)是 6,即不大于 10,因此您完成了转换,使 6一个 0x36。

如果您的目标有 NEG,则使用 AND、OR、ADD、NOT 和 NEG 操作(否则使用 not 并加 1)。请记住,如果您没有直接的 NOT 指令,则与所有的 xoring 是 NOT 操作。(基本上是您想要定位的指令集中可用的基本操作)用您非常熟悉的编程语言或至少支持这些类型的操作和字节处理的编程语言实现和测试您的算法,然后让算法工作并完成只需将高级语言中的每个 and、add、not、sub 等操作转换为汇编。它可能(将)在高级语言中对解决方案进行多次迭代,然后才能类似于易于转换为汇编的形式。如果您现在的组装能力不强,那么完成这项任务所需的复杂性和时间就会成倍增加。尝试同时创建和调试算法并学习汇编并不是两倍的工作量,而是四倍或更多倍的工作量。分而治之。在受控环境中开发算法,然后用目标语言实现。

-1+2=66675(应该是 1)0xFFFF...FFFF + 0x000...00002 = 0x1000000...000001,剪辑到 0x0000...00001(我正在使用任意寄存器大小)66675 = 0x10473。不太清楚你是怎么得到这样的数字的。

-1-1=656745(应该是-2)0xFFFFF....FFFFF + 0xFFFFFF...FFFFF = 0xFFFFFFF...FFFFFFE。656745 = 0xA0569

-1*-1=66757(应该是1)

我很想知道这些的结果是什么

-1+1
-1+3
-2+1
-2+2
-1*-2
-1*-3
-2*-1
-2*-2

正在使用您的计算器。当您这样做时,您可能会开始在结果中看到一种模式。

把问题分成两半,你确定你正在为你的数学运算计算正确的结果,而且只有 ascii 的结果被破坏了吗?还是 ascii 的结果正常工作并且数学运算被破坏了?十六进制很容易,八进制更容易转换,你不需要做反向的事情来快速检查,看到结果后可以手动反转它

while(ax)
{
   dl = (ax&7)+0x30;
   string[ptr++]=dl;
   ax>>=3;
}
string[ptr]=0;

然后显示字符串。手动反转字符串,使用计算器将八进制转换为十进制并检查结果。负二 (-2) 将是 0xFFFFF....FFFFE,因此您会看到八进制,以相反的顺序 67777777777....7777777。因此,一旦您反转字符串,计算器就会让您得到十六进制值 0xFFFFF....FFFE。使用计算器应该很容易看到积极的结果。

(是的,我很清楚您正在使用带有 16 位寄存器的 x86)

于 2013-02-12T05:51:41.123 回答