2013-04-08 28 views
-1

我目前编程大会转换为十六进制字符为8086内装配

当前的任务,我做的是将4个十六进制数字到它的十进制表示。我已经试过遵循我的导师方法,但我很困惑,在我必须将一个临时值乘以十六进制数字的部分,特别是因为我被告知要使它为0,所以每当临时值被乘以它总是会是0对吗?

我到目前为止的代码如下,任何帮助真的很感激!

; ------------------------------------ 
; Name : Gethex 
; Function: converts a word (4 hex digits) into a numerical value 
; Inputs : Upto a word hex values input into the console 
; Outputs : Return within DX the numerical conversion 
; ------------------------------------ 

Gethex: 
MOV BX,0H ;Temp value to 0 
MOV CX,0H ;Counter set to 0 
Gethexloop: 
call Getch 
push DX ; Putch requires DL, need to save current reg 
MOV DL,AL 
call Putch 
pop DX ; restore DL reg 
MOV BH,AH ;Use BH as temp storage as AH will be corrupted 
cmp AL,30H ; ASCII 0 
JL Gethexloop ; If less than 0 jump to the start as not an Alphabetical char 
cmp AL,39H ; ASCII 9 
JLE Nums ; If less or equal to 9 then it will be a number 
cmp AL,46H 
JLE Case ; Start the conversion procedure 
Case: 
SUB AL,10 
jmp Convert 
Nums: 
SUB AL,30 ; Convert to normal number 
Convert: 
push AX ; Prepare to multiply 
MOV AX,BX 
mul BX 
POP AX 
ADD AX,BX 
ADD DX,AX ; final value 
ADD CX,1 ; Increase counter 
cmp CX,3 ; if greater than 4 (0 being included so 3) 
JG EndLoop 
jmp Gethexloop 
EndLoop: 
ret ; return to calling statement 
+2

要求人们发现代码中的错误并不是特别有效。您应该使用调试器来分析问题,追踪程序的进度,并将其与预期发生的情况进行比较。只要两者发生分歧,那么你就发现了你的问题。 (然后如果有必要,你应该构造一个[最小测试用例](http://sscce.org)。) – 2013-04-08 22:42:22

回答

1

只是几个意见...首先,一个数字是一个数字是一个数字。 “十六进制”和“十进制”(和“二进制”和“八进制”)是表示数字的方法 - 数字相同。在一个步骤中将“十六进制表示法”转换为“十进制表示法”会很困难(但可能......我想)。你想要做的是将十六进制表示转换为数字...然后可能将数字转换为其十进制表示,以便我们可以打印它。

我喜欢称之为“迄今为止的结果”的“temp”变量被设置为零以开始,但对于每个字符/数字它不会重置为零!一般程序是将“迄今为止的结果”设置为零,然后对于遇到的每个有效数字,将“迄今为止的结果”乘以基数 - 十进制数,十六进制数16,然后添加新数字...当然,从一个角色转换为一个数字。重复,直到用完字符

mul是一个完美的指令,但它有“隐藏”操作数(在我们的例子中为axdx)。乘以十,我们没有太多的选择,但乘以16可以通过shl reg, 4完成,副作用较少。如果你真的在8086上,只有1cl是有效的操作数。 80186(80286为实际目的 - 80186很少见)中引入了除“1”之外的“直接”。你几乎可以肯定地使用它,但也许你不是“应该”。我怀疑你应该“使用mul” - 在任何情况下都可以更容易地检查溢出(如果你希望这样做 - 将输入限制为4个字符应避免溢出)。

我没有看到你的mov bh, ah行的目的 - ah包含什么“有趣”在这一点上?

几乎所有的汇编程序都会接受cmp al, '0' - 与cmp al, 48cmp al, 30h相同的代码。我发现前者使得教学的目的更加清晰,但它并不重要。

jljg用于有符号数字 - 0FFh将被解释为-1,并将比较为“小于”零。在这段代码中,你不会遇到任何“足够大到负数”的数字,所以它并不重要,但jbja是无符号数(0FFh被解释为255)并且可能“更正确”。这只是一个挑剔的问题,但你也可以了解其中的差异 - 有时候这很重要。

cmp AL,46H 
    JLE Case ; Start the conversion procedure 
Case: 
    SUB AL,10 

同样,我喜欢cmp al, 'F'更好 - 但它产生相同的代码。如果al不小于或等于(再次jbe对于未签名是正确的),则无论如何您都会遇到Case:。我怀疑这是你想要的!我不明白你为什么要减去10,如果你打算减去'0',我会想到37h,或者只有7。

讨厌的用户很可能输入'a'..'f'作为'A'..'F'。为了做一个适当的“toupper”,我们希望确保角色有一个“案例”。在这里,无论如何,我们将拒绝除'A','F'之外的任何东西,因此,如果我们通过强制不具有“大写字母”的字符来生成一些垃圾,则无关紧要。确保你已经处理了十进制数字! and al, 0DFh ; force to uppercase。您可能会也可能不想这样做 - 可以强制用户使用Shift键。 :)

用户输入以回车符结束 - 13或0Dh - (我记得... Linux使用换行 - 10或0Ah - 但我认为dos是13)。您可能需要首先检查 - 十进制或十六进制数字之前。我认为您的当前设置将等待来自用户的4个字符,即使他们已经点击“输入”。可能不是预期的行为...

是的,得到一个调试器,并学习如何使用它。看到一步一步发生的事情会对你有很大的帮助。我曾经喜欢David Lindauer的GRDB ...(如DEBUG只有更亮)...

+0

嗨,弗兰克,感谢您的帮助,我想我现在已经可以工作,调试结果是正确的:)感谢您的友好语气:) – Flak714 2013-04-09 20:34:40

+0

您有任何关于书籍或教程的建议吗? – Flak714 2013-04-10 12:19:25