0

I am trying to write a simple assembly program to add two numbers together. I want the user to be able to enter the values. The problem I am encountering is that when I display a string message and then read a value in, the next time the string is required the first x characters of the string have been overwritten by the data that was entered by the user.

My assumption is that this is related to the use of LEA to load the string into the register. I have been doing this because Macho64 complains if a regular MOV instruction is used in this situation (something to do with addressing space in 64-bits on the Mac).

My code is as follows:

    section .data                                   ;this is where constants go

    input_message db   'Please enter your next number: '
    length equ $-input_message

    section .text                                   ;declaring our .text segment

    global _main                                    ;telling where program execution should start

    _main:                                          ;this is where code starts getting executed
            mov r8, 0
    _loop_values:
            call _get_value
            call _write
            inc r8                                  ;increment the loop counter
            cmp r8, 2                               ;compare loop counter to zero
            jne _loop_values
            call _exit

    _get_value:
            lea rcx, [rel input_message]            ;move the input message into rcx for function call
            mov rdx, length                         ;load the length of the message for function call
            call _write
            call _read
            ret

    _read:
            mov rdx, 255                            ;set buffer size for input
            mov rdi, 0                              ;stdout
            mov rax, SYSCALL_READ
            syscall
            mov rdx, rax                            ;move the length from rax to rdx
            dec rdx                                 ;remove new line character from input length
            mov rcx, rsi                            ;move the value input from rsi to rcx
            ret

    _write:
            mov rsi, rcx                            ;load the output message
            ;mov rdx, rax
            mov rax, SYSCALL_WRITE
            syscall
            ret

    _exit:
            mov rax, SYSCALL_EXIT
            mov rdi, 0
            syscall

The program loops twice as it should. The first time I get the following prompt:

Please enter your next number:

I would the enter something like 5 (followed by the return key)

The next prompt would be:

5 ease enter your next number:

Any assistance would be much appreciated.

Adam McNicol
  • 405
  • 1
  • 4
  • 15
  • 1
    It looks like you're trying to use the same buffer for your prompt and for your input data - so after the first input of "5" you have overwritten the first two characters of the prompt. Try using a separate input buffer for input. – Paul R Feb 04 '15 at 15:21
  • I am not entirely sure what you mean - is the register `RSI` not used to provide the output for a system write and also where the input is stored after a system read? I didn't know this could be customised? I did think about attempting to store the `Please input` string in another register (say `R10`) but because of the way it is loaded using `LEA` then as soon as it is moved to `RSI` the same issue occurs (as it is storing the address to memory for the string rather than the value in the register). Is there a way to use/copy the string without using `LEA`? – Adam McNicol Feb 04 '15 at 18:09
  • Mac use relative addressing, in AT&T syntax you must use something like `lea str(%rip), %rsi`. (str is my string label and %rsi is my destination.) – Parham Alvani Feb 04 '15 at 19:16
  • So for my code it would be something like: `lea %rsi, input_message(%rip)`? I'm not quite sure why the instruction pointer is involved though? – Adam McNicol Feb 04 '15 at 21:32
  • 1
    `rsi` is pointing at the same buffer (`input_message`) for both your write and subsequent read. You need a second buffer for the read (call it e.g. `input_buffer`) and then point `rsi` at this second buffer prior to the read. That way the characters you read won't overwrite the prompt stored in `input_message`. See the OS X example on [this page](https://en.wikipedia.org/wiki/Netwide_Assembler). – Paul R Feb 05 '15 at 00:10

1 Answers1

0

I think all 64-bit code on Mac is required to be rip relative. Absolute addresses are not supported. in this type of addressing you address your symbol relative to rip.
NASM documentation says:

default abs
mov eax,[foo] ; 32−bit absolute disp, sign−extended
mov eax,[a32 foo] ; 32−bit absolute disp, zero−extended
mov eax,[qword foo] ; 64−bit absolute disp

default rel
mov eax,[foo] ; 32−bit relative disp
mov eax,[a32 foo] ; d:o, address truncated to 32 bits(!)
mov eax,[qword foo] ; error
mov eax,[abs qword foo] ; 64−bit absolute disp

and you can also see this question.

Community
  • 1
  • 1
Parham Alvani
  • 2,305
  • 2
  • 14
  • 25