0

I'm currently stuck on a part of my code where I need to ask the user for a number between 0 and 25. If it is outside that range, I have to acknowledge it and request the user to ask for another number. This is done within a 64bit intel architecture.

section .data
    text1 db "Enter shift value: "
    text2 db "Enter original message: "
    text3 db "Current message: "
    text4 db "Encryption: "
    ;lowBound dword 0
    ;upBound dword 25

section .bss
    value resb 5
    message resb 100

section .text
    global main

main:

    call _printText1
    call _getVal
    call _checkVal  

    call _printText2
    call _getMes

    call _printText3
    call _printMes
    
    call _printText4
    ;call _printEncryp

    mov rax, 60
    mov rdi, 0
    syscall

_printText1:
    mov rax, 1
    mov rdi, 1
    mov rsi, text1
    mov rdx, 19
    syscall
    ret

_getVal:
    mov rax, 0
    mov rdi, 0
    mov rsi, value
    mov rdx, 5
    syscall
    ret

_checkVal:
    mov eax, value
    
    ret

This is what I have so far, with the _checkVal function being the place where I would check if the user input is between 0 and 25. Thanks in advance!

1 Answers1

1

What _getVal delivers is a string of characters (hopefully digits) terminated by a newline. You need to convert that into the number's value with a conversion routine. Next is a simplified example that assumes the user will input valid digits and nothing else.

_getVal:
    xor   eax, eax
    xor   edi, edi
    mov   esi, value
    mov   edx, 5
    syscall

    xor   eax, eax             ; Result = 0
    mov   esi, value
    jmp   .begin
.digit:
    inc   esi                  ; Next character
    lea   eax, [rax + rax * 4] ; Result = Result * 10 + NewDigit
    lea   eax, [rdx + rax * 2]
.begin:
    movzx edx, byte [rsi]      ; -> RDX = Newline or ["0","9"]
    sub   edx, 48              ; -> RDX = {-38, 0, 1, ..., 9}
    jnb   .digit

    ret

Now redo if the value is not in [0,25]

main:
    call  _printText1
    call  _getVal              ; -> RAX is value
    cmp   eax, 26
    jnb   main
    ...
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • For essentially the same loop, but stopping on any non-digit character, see [NASM Assembly convert input to integer?](https://stackoverflow.com/a/49548057) - `movzx` load, `sub edx, '0'` / `cmp edx, 9` / `jbe .digit`. Just one extra instruction. Oh, but this wants range-checking of the *whole thing*. Note that a huge input could overflow back to 25, like `4294967321` which is `25 + (1<<32)`. This function will treat that input as `25`. You can check based on string length when you're done, that RSI only advanced at most 2 characters, which rules out being anywhere near u32 wraparound. – Peter Cordes Jul 10 '22 at 22:10
  • It seems wrong that this throws away the return value of the `read` syscall. Consider what will happen if the user presses Ctrl+D. – Joseph Sible-Reinstate Monica Jul 12 '22 at 02:22