我在使用 NASM 程序集实现正确的十进制到二进制、八进制和十六进制转换时遇到了一些问题。我有大部分代码如下,我知道有一些问题我仍在努力解决。我已经在代码中注释了相关信息。
%include "io.mac"
.STACK 100H
.DATA
msg1 db "Please enter a positive integer (max 16 bits): ",0
msg2 db "The binary (base-2) representation of the number is: ",0
msg3 db "The octal (base-8) representation of the number is: ",0
msg4 db "The hex (base-16) representation of the number is: ",0
msg5 db "A",0 ;These will be implemented when I get the
msg6 db "B",0 ;hexadecimal loop working to change 10, 11,
msg7 db "C",0 ;etc. to their hex equivalents.
msg8 db "D",0
msg9 db "E",0
msg10 db "F",0
.UDATA
num1 resw 1
quotient resw 1
remainder resw 1
.CODE
.STARTUP
PutStr msg1
nwln
GetInt [num1]
nwln
PutStr msg2
nwln
mov AX, [num1]
sub BH, BH
binary_loop:
push AX
mov BH, byte 2
div BH ;All loops output the remainders in reverse order at the moment.
mov [remainder], AH ;I was thinking of maybe moving the remainder value
PutInt [remainder] ;to a stack then calling it at the end of the loop,
mov [quotient], AL ;when the quotient value is zero. However,
mov AX, [quotient] ;I do not know enough to make that work. Any help
cmp [quotient], byte 0 ;would be greatly appreciated
jz binary_done ;Could also be je, as both do the same thing
loop binary_loop
binary_done:
nwln
PutStr msg3
nwln
mov AX, [num1]
sub BH, BH
octal_loop:
push AX
mov BH, byte 8
div BH
mov [remainder], AH
PutInt [remainder]
mov [quotient], AL
mov AX, [quotient]
cmp [quotient], byte 0
jz octal_done
loop octal_loop
octal_done:
nwln
PutStr msg4
nwln
mov AX, [num1]
sub BH, BH
hex_loop:
push AX
mov BH, byte 16
div BH
mov [remainder], AH
PutInt [remainder]
mov [quotient], AL
mov AX, [quotient]
cmp [quotient], byte 0
jz done
loop hex_loop
done:
.EXIT
测试 16 位数字 155 的当前输出: 二进制:11011001 八进制:332 十六进制:119
最佳答案
您的代码有 3 个主要问题:
- 它以相反的顺序显示数字
- 它将十六进制数字显示为整数(例如 0xB 显示为 11)
- 它的评论非常糟糕(汇编不是高级语言)
您的代码还有其他问题:
- 没有有效地使用寄存器(而是将内容存储在较慢的变量中)
- 代码重复——接受“base”作为输入的单个例程将使代码大小减半
- 滥用宏(“语言中的语言”);这使得代码更难理解(例如,我无法判断
PutInt
是函数调用还是内联代码,或者它使用了哪些寄存器/垃圾)并且无法优化周围的指令正确
对于第一个问题,最好的办法是在内存中倒序构建一个字符串,然后打印得到的字符串。对于第二个问题,您需要停止使用 PutInt
- 每个数字都应转换为一个字符。
例如(32 位 80x86,NASM,未测试):
;Convert unsigned integer to string
;
;Input
; eax = integer
; ebx = base
;
;Output
; edi = address of string
;
;Trashed
; eax,edx
section .bss
tempString: resb 33 ;Worst case string size is 32 digits
; (for base2), plus string terminator
tempStringEnd:
section .text
convertIntegerToString:
mov byte [tempStringEnd-1],0 ;Store string terminator
mov edi,tempStringEnd-2 ;edi = address to store last character
.nextDigit:
xor edx,edx ;edx:eax = current value
div ebx ;eax = new current value, edx = next digit
add dl,'0' ;dl = character for next digit maybe
cmp dl,'9' ;Is the character correct?
jbe .gotChar ; yes
add dl,'A'-'0'-10 ; no, fix it up
.gotChar:
mov [edi],dl ;Store the character
dec edi ;edi = address for next character
test eax,eax ;Is the current value zero?
jne .nextDigit ; no, do the next digit
ret ;Done, EDI = address of completed string
关于assembly - 使用 NASM 程序集将 16 位十进制数转换为其他基数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29885580/