I am trying to simulate a scanf in assembly that takes different suffixes (h-hex,b-bin etc). This worked fine for unsigned values, but after adding those 5 lines (commented below, to enable signed values), I ran into problem of missing front digit if I entered unsigned value, but works as expected for signed values.
;Linux Mint 17 (64-bit)
;./fasm scanf.asm
;./scanf
format elf64 executable
include 'PROC64.INC'
include 'IF.INC'
push tstValue
call SCANF
push 1 ;sign
push [tstValue] ;No problem here
call DISP_INT
call EXIT
tstValue dq 0
proc SCANF,value
locals
flag db 0
key rb 1
endl
push rsi rdi rax rcx rdx
push rbx r8 r9 r10
xor r10,r10
xor r8,r8 ;loop index
lea rsi,[key]
mov edx,1
xor edi,edi
xor eax,eax ;Problem starts after I
syscall ;added these
cmp byte[key],'-' ;5 new lines to allow signess
jne .begin ;
mov byte[flag],1 ;
.begin:
xor rax,rax
syscall
mov r10b,byte[rsi]
cmp r10b,0ah
jz .select
push r10
inc r8
jmp .begin
.select:
pop rax
cmp al,'h'
je .hexadecimal
cmp al,'H'
je .hexadecimal
cmp al,'b'
je .binary
cmp al,'B'
je .binary
cmp al,'o'
je .octal
cmp al,'O'
je .octal
cmp al,'d'
je .decimal
cmp al,'D'
je .decimal
push rax ;if no suffix, defaults to decimal
inc r8 ;re-adjust index
.decimal:
xor r9,r9
pop rax
sub rax,30h
add r9,rax
mov rcx,10
mov rbx,10
dec r8
jmp .translate
.hexadecimal:
xor r9,r9
pop rax
.if al >= 'a' & al <= 'f'
sub rax,27h
.elseif al >= 'A' & al <= 'F'
sub rax,7h
.endif
sub rax,30h
add r9,rax
mov rcx,16
mov rbx,16
dec r8
jmp .translate
.octal:
xor r9,r9
pop rax
sub rax,30h
add r9,rax
mov rcx,8
mov rbx,8
dec r8
jmp .translate
.binary:
xor r9,r9
pop rax
sub rax,30h
add r9,rax
mov rcx,2
mov rbx,2
dec r8
jmp .translate
.translate:
dec r8
jz .exit
pop rax
.if al >= 'a' & al <= 'f'
sub rax,27h
.elseif al >= 'A' & al <= 'F'
sub rax,7h
.endif
sub rax,30h
mul rcx
add r9,rax
mov rax,rbx
mul rcx
mov rcx,rax
jmp .translate
.exit:
mov rax,[value]
.if [flag] = 1
neg r9
.endif
mov [rax],r9
pop r10 r9 r8 rbx
pop rdx rcx rax rdi rsi
ret
endp
I checked all the registers before that .begin label and they all working as expected (so that syscall should have the correct arguments for reading a single character, eax=0,edx=1,edi=0, rsi points to the character). If I deleted all those 5 lines in question, the program works normally but that leaves me with unsigned program only.
Can anybody help me pointing out what could be the problem? I seem to be running out of idea. I didn't make any push or increase my index (r8) prior to calling .begin. That should cancel out stack or indexing problem.
This is the output for unsigned
3455 ;keyboard input
455
This one works (for signed)
-3455
-3455
Thank you in advance
The fourth line that you've commented must jump 2 lines further. That's why you're losing the first digit of an unsigned value!
xor eax,eax ;Problem starts after I
syscall ;added these
cmp byte[key],'-' ;5 new lines to allow signess
jne .beginEx ;
mov byte[flag],1 ;
.begin:
xor rax,rax
syscall
.beginEx:
mov r10b,byte[rsi]