NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: Anonymous on June 19, 2014, 07:47:38 PM
-
EDIT:
(Sorry decimal to hexadecimal my bad)
I have been trying to make a decimal to hexadecimal converter and I need to use conditional jumps to test if the number is 10 or over so I can print a letter instead of a number here is my code so far
toHex:
;[reg+k*ind]
push rbx;preserve value of rbx
mov rbx, 16
xor rcx, rcx;clear out rcx to use as counter
mov r9, Array;mov in the address of the array
dec rcx
mov qword [r9+8*rcx], 0;pre zero it
inc rcx
.top:
xor rdx, rdx;clear out rdx for division
div rbx;divide rax by 16
mov qword [r9+8*rcx], rdx;move the remainder into the array
inc rcx;increase the counter
cmp rax,0;if rax is not 0 then keep going
jne .top
.nextDgt:
dec rcx;get ready for the next
cmp qword [r9+8*rcx], 10;if greater than or equal to 10 then jump to printChar
jae printChar
lea r8, [r9+8*rcx];get the address of the next remainder to pass into itoa
mov r10, rcx;preserve the counter
call itoa;print the remainder
mov rcx, r10;restore the counter
printChar:
call PrintSTR
cmp qword [r9+8*rcx], 0;if 0 then done .
jne .nextDgt
pop rbx;restore value of rbx
.done:
ret
PrintSTR:
cmp qword [r9+8*rcx], 10
je n10
cmp qword [r9+8*rcx], 11
je n11
cmp qword [r9+8*rcx], 12
je n12
cmp qword [r9+8*rcx], 13
je n13
cmp qword [r9+8*rcx], 14
je n14
cmp qword [r9+8*rcx], 15
je n15
n10:
mov rdx, 8 ;length
mov rsi, 'A';variable
mov rdi,1
mov rax, 1
syscall
jmp .Return
n11:
mov rdx, 8 ;length
mov rsi, 'B';variable
mov rdi,1
mov rax, 1
syscall
jmp .Return
n12:
mov rdx, 8
mov rsi, 'C'
mov rdi,1
mov rax, 1
syscall
jmp .Return
n13:
mov rdx, 8
mov rsi, 'D'
mov rdi,1
mov rax, 1
syscall
jmp .Return
n14:
mov rdx, 8 ;length
mov rsi, 'E';variable
mov rdi,1
mov rax, 1
syscall
jmp .Return
n15:
mov rdx, 8 ;length
mov rsi, 'F';variable
mov rdi,1
mov rax, 1
syscall
.Return:
ret
but it is giving me these errors :
Convert.asm:79: error: symbol `printChar.nextDgt' undefined
Convert.asm:105: error: symbol `n10.Return' undefined
Convert.asm:114: error: symbol `n11.Return' undefined
Convert.asm:123: error: symbol `n12.Return' undefined
Convert.asm:132: error: symbol `n13.Return' undefined
Convert.asm:141: error: symbol `n14.Return' undefined
-
Wow. I'm not even sure what a "hexadecimal to hex converter" is. I guess you want to convert a number into an ascii representation in hex of the number.
In any case, the errors you're getting are because of the way Nasm handles "local labels". A label starting with a '.' has a scope from the previous "non-local" label to the next "non-local" label. You've interrupted this scope with a "non-local" label between the local label and where it's used.
What you're trying to do isn't going to work anyway... "mov rsi, 'A'"... sys_write expects the address of a buffer where the text can be found in rsi, not the text itself.
The conditional jump you want is probably...
; ASSume the number (not yet a character) is in rdx
; all we want is dl
cmp dl, 10
jbe .skip
add dl, 7 ; this gets us from '9' to 'A'
.skip:
add dl, '0'
; now dl should be a character from '0' to '9' or 'A' to 'F'
; put it in a buffer (or print it now)
A separate conditional jump for each number from 10 to 15 is overkill.
When converting to a decimal representation of a number, we don't have much choice but to divide by 10. As you know, the remainders come in the "wrong order" so we have to deal with that. Converting to a hexadecimal representation is much simpler, actually. Each 4 bits is going to be a character. We know in advance how many of them there are going to be (I like to print the leading zeros in a hex representation - you don't have to). We can divide by 16 (or any power of two) with a shift, avoiding the slow "div" instruction. We can even get the characters in the "right order" if we do it right. I like a rotate, rather than a literal shift...
itoh:
; ASSume the number is in rax
: maybe rdi would be better for 64-bit code
; unlike "div" we aren't forced to use rax
; address of buffer in rsi
; at least 16 bits - 17 if we want zero terminator
mov rcx, 16 ; loop counter
.top:
rol rax, 4 ; get top 4 bits in bottom 4 bits
; make a copy of it, 'cause we're going to trash it
mov rdx, rax
and rdx, 0Fh ; isolate the bits we want
cmp dl, 10
jbe .skip
add dl, 7 ; bump it up to 'A' to 'F' if we need to
.skip:
add dl, '0' ; make it a character
mov rsi, [dl] ; put it in our buffer
inc rsi ; normal "front to back" order
dec ecx
jnz .top
mov byte [rsi], 0 ; zero-terminate string?
; although we know its length
ret
At this point, rax (or wherever we put the number) should be rotated "all the way around" and should hold its original value. As you know, I'm clueless in 64-bit code, so this may not be right, but "something like that" should be simpler than the way you're trying to do it.
Best,
Frank
-
Oops!
cmp dl, 10
jbe .skip
We don't want to jump over the "add 7" if it's equal! Just "jb".
Best,
Frank
-
Hi frank thanks and I figured out a simpler way to do it than the way I was trying to do it here is the finished product:
toHex:
;[reg+k*ind]
push rbx;preserve value of rbx
mov rbx, 16
xor rcx, rcx;clear out rcx to use as counter
mov r9, Array;mov in the address of the array
dec rcx
mov qword [r9+8*rcx], 0;pre zero it
inc rcx
.top:
xor rdx, rdx;clear out rdx for division
div rbx;divide rax by 16
mov qword [r9+8*rcx], rdx;move the remainder into the array
inc rcx;increase the counter
cmp rax,0;if rax is not 0 then keep going
jne .top
.nextDgt:
dec rcx;get ready for the next
lea r8, [r9+8*rcx];get the address of the next remainder to pass into itoa
cmp qword [r9+8*rcx], 10
jnae .skip;skip if not greater than or equal to
add qword [r9+8*rcx], 55;Convert to letter
mov rdx, 8 ;length
lea rsi,[r9+8*rcx] ;variable
mov rdi,1
mov rax, 1
syscall
jmp .next
.skip:
mov r10, rcx;preserve the counter
call itoa;print the remainder
mov rcx, r10;restore the counter
.next:
cmp qword [r9+8*rcx], 0;if 0 then done
jne .nextDgt
pop rbx;restore value of rbx
ret