我正在试着做一个可以对负数进行算术运算的计算器。这里的代码用于将输入的数字转换为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发布于 2013-02-12 13:51:41
了解问题,然后对其应用语言。我会先用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或0xFFFFF或0xFFFFFFFFF等。因此,当前运算符是+,0x2B,下一个字符是0x32数字2,并用0xF提取字符串的末尾2.下一个字符,所以现在应用操作-1,0xFF如果8位是0xFF+0x02 = 0x101,则加2,0x02如果8位是0x01,结果-1 +2= 1,然后你必须将其返回ascii,在这种情况下1+ 0x30 = 0x31,但对于小于10的数字来说,这只是一件容易的事情。
"-1*-1" is 0x2D,0x30,0x2A,0x2B,0x30当你看到0x2A和0x2B行中的两个运算符时,问题就来了,在这种情况下,作为人类,我们知道在这两种情况下,减号与后面的数字求反,然后执行乘法。
更大的数字,如果你支持他们,也必须处理。
"12+34" 0x31,0x32,0x2B,0x33,0x340x31是一个从0x1中剥离出来的数字,但0x32也是一个数字,所以将0x1乘以10,然后将从0x32中剥离出来的2相加,得到一个0xC,然后将该数字(十进制12)的累加部分加上加号0x2B,然后以同样的方式将另一个数字从0x33中剥离出来,再乘以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和add 1)。请记住,如果没有直接的NOT指令,与所有1进行异或运算就是NOT操作。(基本上是你想要针对的指令集中的基本操作)在你非常熟悉的编程语言中实现和测试你的算法,或者至少一种支持这些操作和字节处理的编程语言,让算法工作并完成,然后简单地将高级语言中的每个and、add、not、sub等操作转换成汇编语言。它可能(将)在高级语言中对解决方案进行多次迭代,然后才能类似于一种易于转换为汇编的形式。如果你现在不擅长组装,那么你就会增加完成这项任务所需的复杂性和时间。试图同时创建和调试算法并学习汇编并不是两倍的工作量,而是四倍甚至更多的工作量。分而治之。在受控环境中开发算法,然后在目标语言中实现它。
-1+2=66675 (应该是1) 0xFFFF...FFFF + 0x000...00002 = 0x1000000...000001,clips to 0x0000...00001 (我使用任意的寄存器大小) 66675 = 0x10473。不太确定你是怎么得到这样的数字的。
-1\f25 0xFFFFF....FFFFF + 0xFFFFFF...FFFFF = 0xFFFFFFF...FFFFFFE -1\f6=-1\f25 656745 -1\f6(应该是)。-2\f25 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 (-2)是0xFFFFF....FFFFE,所以在八进制中你会看到,倒序为67777777777...7777777。因此,一旦你颠倒了字符串,计算器就会把你带到十六进制值0xFFFFF....FFFE。不过,使用计算器可以很容易地看到积极的结果。
(是的,我很清楚您使用的是带16位寄存器的x86 )
https://stackoverflow.com/questions/14825368
复制相似问题