0

Why does this work,

SYS_READ equ 0
SYS_WRITE equ 1
SYS_EXIT equ 60

STDIN equ 0
STDOUT equ 1

section .data
    my_char: db 'a'

global _start

section .text
    _start:
        mov rax, SYS_WRITE
        mov rdi, STDOUT
        mov rsi, my_char
        mov rdx, 1
        syscall
        
        mov rax, SYS_EXIT
        mov rdi, 0
        syscall

But this doesn't?

...

section .text
    _start:
        mov rax, SYS_WRITE
        mov rdi, STDOUT
        mov rsi, 'a' ; Replacing my variable with an immediate byte operand
        mov rdx, 1
        syscall
        
        mov rax, SYS_EXIT
        mov rdi, 0
        syscall

I would think it's doing the same thing in memory, the first one setting the value of the rsi register to 'a', and the second one doing the same, only I'm not using a variable.

Within memory, what is different? Is there any way to do something similar to my second example?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
coulomb
  • 698
  • 6
  • 16
  • 3
    No, the first one loads the address which is helpful since `write` expects an address. – Jester Nov 09 '22 at 21:59
  • 1
    `mov rsi, 'a'` is an immediate load of the value 0000_0000_0000_0061h. `mov rsi, my_char` loads an address to a data byte in memory. `mov rsi, qword [my_char]` would load a similar value (61h) into `rsi` if you declared the variable with `dq`. Alternatively `movzx rsi, byte [my_char]` also loads 61h into `rsi`. As @Jester stated, the system call expects an address, not a literal codepoint value. – ecm Nov 09 '22 at 22:03
  • 1
    The immediate form your speaking of would have a different signature / parameter list than the pointer form, namely an immediate instead of pointer and no need for length parameter. Typically, different signatures require different syscalls, just like with functions. Sadly, the signature you're wanting isn't provided for by that operating system. – Erik Eidt Nov 09 '22 at 23:05
  • @ecm so would I be able to do `mov r8, 'a'`, `mov rsi, r8`? Does a register count as an address? – coulomb Nov 10 '22 at 01:49
  • It seems that you want the printed text appear directly in the instruction `mov rsi, 'text to print'`. This is called **literal string**. IBM invented syntax for literals using *leading equal sign* half century ago (and I adopted it to €ASM): `mov rsi, =b 'text to print'` which silently defines `db 'text to print'` somewhere in .`data` section and loads **its offset** to `rsi`, but this is not supported in NASM. – vitsoft Nov 10 '22 at 07:30
  • 2
    @coulomb No, `mov rsi, r8` again will load the value 61h into `rsi`. Registers do not have addresses, you cannot point a system call that expects a buffer at a memory address to use a register. You could do `mov al, 'a'` \ `push rax` \ `mov rsi, rsp` however, creating a small buffer that's stored in memory on the stack. You could then discard that later by using a `pop` or otherwise resetting `rsp`. – ecm Nov 10 '22 at 08:43

0 Answers0