1

I have written simple hello_world program in nasm.

segment .text               ; code section
    global _start           ; must be declared for linker

    _start:                 ; tell linker entry point
        mov edx, len        ; message len (DX is for data register)
        mov ecx, msg        ; message to write (CX is for count register)
        mov ebx, 1          ; (stdout) file descriptor
        mov eax, 1          ; system call number for write system call
        int 0x80            ; call kernel

        mov eax, 1          ; system call number for exit system call
        int 0x80            ; call kernel

section .data
    msg db "Hello, World", 0xa
    len equ $ - msg

so when i am compiling this program with elf64 flag $nasm -f elf64 hello_world.nasm

and then linking with ld $ld hello_world.o

finally when i ran a.out it not write anything to stdout.

when i opened file unistd_64.h to show which system call is calling for no 1.

// /usr/include/asm/unistd_64.h

#ifndef _ASM_X86_UNISTD_64_H
#define _ASM_X86_UNISTD_64_H 1

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
#define __NR_stat 4

As you can see for write system call number is 1. this program will work if i put 4 instead of 1 but 4 is specified in unistd_32.h and i also compiled with elf64 flag so why it is not working for 64 bit?

for your reference unistd_32.h

#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H 1

#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
Visrut
  • 360
  • 4
  • 14
  • Related: [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730) - `int 0x80` invokes the 32-bit ABI, with numbers from `unistd_32.h` – Peter Cordes Oct 26 '22 at 17:43

1 Answers1

1

You are making a mistake in which you need to use the sysv-64-abi which states that functions parameters to be passed to rdi, rsi, rdx, rcx. In addition exit syscall number is decimal 60 not 1. also you mistyped section .text. Any you need to use syscall and not old slower int soft interrupt instruction to trap into kernel.

section .text               ; code section
    global _start           ; must be declared for linker

    _start:                 ; tell linker entry point
        mov rdx, len        ; message len (DX is for data register)
        mov rsi, msg        ; message to write (CX is for count register)
        mov rdi, 1          ; (stdout) file descriptor
        mov rax, 1          ; system call number for write system call
        syscall            ; call kernel

        mov rax, 60          ; system call number for exit system call
        syscall            ; call kernel

section .data
    msg db "Hello, World", 0xa
    len equ $ - msg
KMG
  • 1,433
  • 1
  • 8
  • 19
  • can you give me reason why you used `syscall` instead of `int 0x80` because when i used `syscall` it works. – Visrut Oct 11 '21 at 09:54
  • 1
    @Visrut ```https://stackoverflow.com/questions/12806584/what-is-better-int-0x80-or-syscall-in-32-bit-code-on-linux``` – KMG Oct 11 '21 at 10:06
  • `syscall` is not a function call. We indeed want to follow the SysV convention for it, but we can't fully adhere it, because the 4th argument register for `syscall` can't be `rcx` as `rcx` will be clobbered by the nature of `syscall` instruction itself to save the next `rip` when it returns to userspace. – Ammar Faizi Oct 12 '21 at 17:39
  • So the registers usage to pass argument to `syscall` will be `rdi`, `rsi`, `rdx`, `r10`, `r8`, `r9` respectively. Just to emphasize... Yes, it is `r10`, not `rcx` – Ammar Faizi Oct 12 '21 at 17:41