Reputation: 31
I am having some issues implementing a proper decimal to binary, octal, and hex conversion using NASM assembly. I have most of the code as follows, which I know has some issues that I'm still working on getting fixed. I have commented relevant information in the code.
%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
Current output for a test 16-bit number of 155: Binary: 11011001 Octal: 332 Hex: 119
Upvotes: 3
Views: 2604
Reputation: 37232
Your code has 3 main problems:
Your code also has other issues:
PutInt
is a function call or inline code, or which registers it uses/trashes) and makes it impossible to optimise the instructions around it correctlyFor the first problem, the best approach is to build a string in memory in reverse order, and then print the resulting string. For the second problem you need to stop using PutInt
- each digit should be converted to a character.
For example (32-bit 80x86, NASM, untested):
;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
Upvotes: 2