### Author Topic: Conditional jumping  (Read 10024 times)

#### Anonymous

• Jr. Member
• Posts: 78
• Country:
##### Conditional jumping
« on: June 19, 2014, 07:47:38 PM »
EDIT:
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:retPrintSTR: 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 »

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### 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

#### Frank Kotler

• NASM Developer
• Hero Member
• Posts: 2667
• Country:
##### 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

#### Anonymous

• Jr. Member
• Posts: 78
• Country:
##### 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 rbxret`
« Last Edit: June 20, 2014, 01:14:22 AM by Anonymous »