Author Topic: Conditional jumping  (Read 12695 times)

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Conditional jumping
« 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
Code: [Select]
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

« Last Edit: June 20, 2014, 12:29:59 AM by Anonymous »
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Conditional jumping
« Reply #1 on: June 20, 2014, 12:06:42 AM »
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...
Code: [Select]
; 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...
Code: [Select]
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


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Conditional jumping
« Reply #2 on: June 20, 2014, 01:02:50 AM »
Oops!
Code: [Select]
    cmp dl, 10
    jbe .skip
We don't want to jump over the "add 7" if it's equal! Just "jb".

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: Conditional jumping
« Reply #3 on: June 20, 2014, 01:08:38 AM »
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:
Code: [Select]
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

« Last Edit: June 20, 2014, 01:14:22 AM by Anonymous »
Thanks in advance, Anonymous