2

I'm working on a simple tutorial for iterating over a string with readable and changeable code. This is apart of a simple operating system project that is in the works. I'm documenting all the confusions I have while learning assembly and then presenting them in an understandable way but in the most simple. The code I wrote in its current form displays one character, the finished form will go through the string until it hits the null terminator. I'm wondering why when i doing the following works.

mov rsi, message + 2 ;print specific character

however when i do

mov rsi, message + rbp ;print specific character

I get an error: invalid operand type. I have searched stackoverflow(and other search engines) and have done random attempts to find the the offset operator to achieve the result of the first working code. I thought it was a plus operator, or maybe the colon(:) or perhaps the brackets([]), not sure how to indicate offset here.

Here is the working code version, how do i turn it into the "dynamic" version of picking the specific character to print?

global _start

section .data
    message: db 'hello world!', 10

section .text
_start:
    mov rbp, 1 ;tracks position of character to print

    mov rax, 1  ;system call number for "write"
    mov rdi, 1  ;first argument, where to write (terminal)
    mov rsi, message + 2 ;second argument, print specific character
    mov rdx, 1 ;third argument, bytes to write
    syscall     ;envoke process for the parameters/virtually placed lines


mov rax, 60
syscall

I have an alternative version that gets the full string length and then the syscall uses the string length to print out the entire string, however in this version i eventually want to demonstrate string transformations, splitting, and comparisons.

  • 1
    there is no `mov reg, reg + immediate` instruction. Keep taking a peek at every instruction you use in the instruction reference guide (like the unofficial shortened ones like http://www.felixcloutier.com/x86/ ) ... after some while you will get good feel for which instructions do exists, and which don't. (there's of course `mov rsi,[message + rbp]`, but that's something completely different, reading value from memory, but this addressing mode can be used by `lea` instruction to actually just do that calculation, and not contact memory chip for value, and use the "address" itself as result). – Ped7g Mar 15 '18 at 10:06
  • @Ped7g That quick sheet is so handy, I can't even begin to express my gratitude. I have been having to write notes on registers and instructions and re-reading entire manuals and guide books to find a particular instruction. – Dahlia Radio Mar 15 '18 at 21:06

1 Answers1

2

You need to add a constant to a value in a register. For an address that fits in 32 bits (like any static address in a normal non-PIE executable), you can use it as a 32-bit immediate operand to add. i.e.

; rsi contains an offset into the array, e.g. from mov esi, 1

add  rsi, message
; add rsi, message + 2    ; you can of course use constant offsets from labels, too

(If you know that your index is within the static object, you can use add esi, message and still get a valid 64-bit pointer, because static objects are in the low 2GiB of virtual address space.)

Or to copy-and-add, use lea rsi, [rbp + message]


If you can't use 32-bit absolute addresses, use a RIP-relative LEA to get the address of your static object, then separately add the register value.

lea  rsi, [rel message]
add  rsi, rbp

(Use default rel to make that the default for addressing modes like [message].)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • the lea rsi, [rbp + message] instruction worked flawlessly. I appreciate your time in assisting me. About to test the rest and continue work. – Dahlia Radio Mar 15 '18 at 21:13