我正在尝试制作一个用负数执行算术运算的计算器。此处的代码用于将输入的数字转换为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
答案 0 :(得分:1)
了解问题然后应用语言。我会先用C语言编写,然后再装入。
你提到ASCII,但是我没有看到你从ascii的转换。
例如,当您说“-1 + 2”表示您的输入是那些项目的ASCII字符时
0x2D,0x31,0x2B,0x32
解析这个问题的一种方法是:
您需要将0x2D识别为减号操作,然后在ascii中按下数字1,即0x31。假设这些是十进制数,则剥离0x30,例如0xF。下一个字符是+,0x2B,一个运算符,所以现在你可以返回并获取完整的数字1并在之前应用运算符。但是你需要一个寄存器大小是这些8位值还是16位或32位或64位?当你否定你得到0xFF或0xFFFF或0xFFFFFFFF等时,8位1是0x01,16是0x0001等。所以当前运算符是+,0x2B,下一个字符是0x32数字2,并且用0xF来提取2.下一个字符结束字符串,所以现在应用操作-1,0xFF如果8位,加上2,0x02如果8位是0xFF + 0x02 = 0x101,当剪切到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,0x34
0x31是一个数字剥离0x1,但0x32也是一个数字,所以乘以0x1乘以10,然后加上从0x32剥离的2给出一个0xC,无论是累积该数字(十进制12),然后是加号0x2B然后另一个数字处理相同的方式剥离0x33的3乘以10,加上4剥离0x34给出十进制34(0x22),然后添加这两个数字0x0C + 0x22 = 0x2E(十进制46)。在这种情况下,我假设所需的结果是0x34,0x46,ascii字符串为“46”。为了达到这个目的,你需要将0x2e除以10,因为它大于10,得到4的第一个数字,余数(模10)是6,不大于10所以你完成转换使得6一个0x36。
如果您的目标有NEG,则使用AND,OR,ADD,NOT和NEG操作(否则使用not并添加1)。请记住,如果您没有直接的NOT指令,则使用所有的xoring是一个NOT操作。 (基本上是你想要指定的指令集中可用的基本操作)用你熟悉的编程语言实现和测试你的算法,或者至少支持这些操作和字节处理的算法,让算法工作和完成然后只需将您的高级语言中的每个和,添加,而不是,等等操作转换为汇编。它可以(WILL)在高级语言中进行多次迭代,然后它类似于易于转换为汇编的表单。如果你现在在装配方面不够强大,那么你就会增加完成这项任务所需的复杂性和时间。尝试创建和调试算法并同时学习汇编不是工作量的两倍,而是工作量的四倍或更多倍。分而治之。在受控环境中开发算法,然后以目标语言实现。
-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)