Welcome Guest ( Log In | Register )

Outline · [ Standard ] · Linear+

 Anyone in system programming with Linux x64?

views
     
TSFlierMate
post Jul 24 2021, 02:06 PM, updated 2y ago

On my way
****
Validating
543 posts

Joined: Nov 2020
Recently I started my journey in system programming with Linux.
Here's a useful website just for that, https://www.kernel.org/doc/man-pages/

As I dig into "/usr/include/x86_64-linux-gnu/asm" directory, I found lists of syscall numbers in unistd_32.h and unistd_64.h.

Here's the first 13 lines of the unistd_64.h header file:
CODE

#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
#define __NR_fstat 5
#define __NR_lstat 6
#define __NR_poll 7
#define __NR_lseek 8
#define __NR_mmap 9
#define __NR_mprotect 10


sys_read = 0, sys_write = 1, sys_exit = 60 (not listed above).

For example, here's a piece of Assembly code to call sys_read and sys_write function. It actually reads a line from console and then writes the line back to console.
As follows:

CODE

format ELF64 executable 3

segment readable executable

entry $

mov edx,256
lea rsi,[buf]
mov edi,1
xor eax,eax; sys_read
syscall

mov edx,256
lea rsi,[buf]
mov edi,1; STDOUT
mov eax,1; sys_write
syscall

xor edi,edi; exit code 0
mov eax,60; sys_exit
syscall

segment readable writeable

buf rb 256

(This ELF64 binary file is 230 bytes only, way smaller than similar Windows PE binary file)

This is still very basic, in demonstrating the 64-bit syscall in ELF64 binary file format.

As shown somewhere in the Linux manual (link given in the first paragraph), parameters preceding a 64-bit syscall is as follows:

CODE

; r9  ; 6th param
; r8  ; 5th param
; r10  ; 4th param
; rdx  ; 3rd param
; rsi  ; 2nd param
; rdi  ; 1st param
; eax  ; syscall_number
; syscall


But in 32-bit Linux system programming, we use "int 0x80" instead of "syscall". Corrections are welcomed as I am beginner to Linux kernel.

And one funny hex value from the Linux manual no doubt is: (Look! What's the magic number :=)

CODE

(snipped)
mov  rdi,0xfee1dead; MAGIC1
mov eax,169; sys_reboot
syscall


It resembles the English phrase "feel dead", yes, for sys_reboot (as if computers were to "feel dead" before powered down or system restart ;=).

This post has been edited by FlierMate: Jul 28 2021, 02:37 AM
TSFlierMate
post Jul 24 2021, 10:29 PM

On my way
****
Validating
543 posts

Joined: Nov 2020
For anyone who like DIY coding, can try this one!

Once compiled and run, it displays the full 48-char processor name in Terminal window:
user posted image

Code? It's in Assembly:

CODE
format ELF64 executable 3

segment readable executable

entry $

      mov     eax, 0x80000002
      cpuid
      mov     dword [cpu], eax
      mov     dword [cpu + 4], ebx
      mov     dword [cpu + 8], ecx
      mov     dword [cpu + 12], edx
      mov     eax, 0x80000003
      cpuid
      mov     dword [cpu + 16], eax
      mov     dword [cpu + 20], ebx
      mov     dword [cpu + 24], ecx
      mov     dword [cpu + 28], edx
      mov     eax, 0x80000004
      cpuid
      mov     dword [cpu + 32], eax
      mov     dword [cpu + 36], ebx
      mov     dword [cpu + 40], ecx
      mov     dword [cpu + 44], edx
      mov     byte [cpu + 48],0xA  ;Append line feed

      mov     edx,49
      lea     rsi,[cpu]
      mov     edi,1      ; STDOUT
      mov     eax,1     ; sys_write
      syscall

      xor     edi,edi    ; exit code 0
      mov     eax,60    ; sys_exit
      syscall

segment readable writeable

cpu    rb      49


It was originally written for Win32, but to target Linux x64 , I have removed the reference to Win32 API and use Linux system call instead.

Note that reserved data is 49 bytes (although processor name is 48 chars only) so that additional line feed (0xA) could be appended at the end of the line.

It performs sys_write system call to display the processor name, and then sys_exit system call to quit the program.

cpuid, with different eax value as paramater, can be used to return a lot of information about computer processor, such as if AVX is present or not. However, this is beyond the discussion of this article.

UPDATE:
Here's another code for displaying the basic CPU info:

CODE

; "AuthenticAMD" – AMD
; "GenuineIntel" – Intel
format ELF64 executable 3

segment readable executable

entry $

      xor     eax, eax
      cpuid
      mov     dword [cpu], ebx
      mov     dword [cpu + 4], edx
      mov     dword [cpu + 8], ecx
      mov     byte [cpu + 12],0xA      ;Append line feed

      mov     edx,13
      lea     rsi,[cpu]
      mov     edi,1    ; STDOUT
      mov     eax,1  ; sys_write
      syscall

      xor     edi,edi    ; exit code 0
      mov     eax,60  ; sys_exit
      syscall

segment readable writeable

cpu    rb      13


Two most common value returned are:
* "AuthenticAMD" – AMD
* "GenuineIntel" – Intel



You'll need Flat Assembler for Linux to compile it.

1. Download https://flatassembler.net/fasm-1.73.27.tgz
2. Extract it to anywhere you like (/home/xxxx/fasm), no installation required
3. Save my Assembly code as text file (e.g. cpuname.asm)
4. Go to fasm folder, and then type ./fasm.x64 cpuname.asm
5. Voila, you're ready to run via command-line ./cpuname

This post has been edited by FlierMate: Aug 2 2021, 04:15 AM
TSFlierMate
post Oct 17 2021, 02:45 PM

On my way
****
Validating
543 posts

Joined: Nov 2020
Look! I made a 129-byte tiny ELF64 which prints "Hello!" in terminal window.

You can't achieve this using ordinary programming mode, unless we code the headers as well bit by bit.

Here it is:
CODE
ORG 0x400000
       
USE64        
       db 0x7F, "ELF"     ; EI_MAG0, EI_MAG1, EI_MAG2, EI_MAG3  
       db 0x02            ; EI_CLASS (2=ELFCLASS64)
       db 0x01            ; EI_DATA (1-ELFDATA2LSB)
       db 0x01            ; EI_VERSION
       db 0x03            ; EI_OSABI
       db 0x00
 @@    db "Hello!",0x0A
 msg_size = $ - @b
       dw 2               ; ET_EXEC               e_type
       dw 0x3E            ;                       e_machine
       dd 1               ;                       e_version
       dq _start - $$ + 0x400000 ;                e_entry
       dq phdr - $$       ;                       e_phoff
       dq 0x00            ;                       e_shoff
       dd 0x00            ;                       e_flags
       dw phdr - $$       ;                       e_ehsize
       dw _start - phdr   ;                       e_phentsize
       dw 0x01            ;                       e_phnum
      ;dw 0x40            ;                       e_shentsize
      ;dw 0x00            ;                       e_shnum
      ;dw 0x00            ;                       e_shstmdx

phdr:
       dd 0x01            ; PT_LOAD               p_type
       dd 0x05            ; PF_X + PF_W + PF_R    p_flags
       dq 0x00            ;                       p_offset
       dq 0x400000        ; 0x400000              p_vaddr
       dq 0x400000        ; 0x400000              p_paddr
       dq _end-_start     ;                       p_filesz
       dq _end-_start     ;                       p_memsz    
       dq 0x100           ;                       p_align            
             
_start:
      ;lea esi, [@b]
       mov esi, 0x400009
       mov dl, msg_size
       mov al, 1        ; sys_write
      ;mov dil, 1      ; STDOUT = 1
       syscall
       mov al, 60       ; sys_exit
       syscall
_end:    


Please feel free to improve it, to create binary file size less than 129 bytes that is working on Linux x64.

To compile it, download FASM for Linux, then use:
CODE

./fasm.x64 tiny.asm
chmod +x tiny.bin
./tiny.bin


Hope you are thrilled with this tiny ELF64 example! biggrin.gif


cikelempadey
post Dec 26 2021, 08:46 AM

Getting Started
**
Junior Member
86 posts

Joined: Apr 2011
From: Your Nen Nen


i think my posts about manual elf dynamic linking and loadable kernel module still exists on fasm's board that leads to the author improving the fasm linux build with dynamic linking and other supports.

try search the board by author "nocona"
TSFlierMate
post Dec 28 2021, 06:23 AM

On my way
****
Validating
543 posts

Joined: Nov 2020
.........

This post has been edited by FlierMate: Dec 31 2021, 05:15 PM
TSFlierMate
post Dec 28 2021, 06:28 AM

On my way
****
Validating
543 posts

Joined: Nov 2020
........

This post has been edited by FlierMate: Dec 31 2021, 05:15 PM
TSFlierMate
post Dec 28 2021, 06:42 AM

On my way
****
Validating
543 posts

Joined: Nov 2020
............

This post has been edited by FlierMate: Dec 29 2021, 07:11 PM
FlierMate1
post Jun 23 2022, 03:55 PM

Getting Started
**
Validating
139 posts

Joined: Jun 2022
I try it myself on new computer, which is AMD CPU, and this is the output: rclxs0.gif

user posted image

This post has been edited by FlierMate1: Jun 28 2022, 03:13 PM
FlierMate1
post Aug 11 2022, 05:40 PM

Getting Started
**
Validating
139 posts

Joined: Jun 2022
For a 32-bit Linux program, this is an example program in NASM to print "Hello World":

Code

section .text

global _start

_start:

mov ecx, msg ;pointer to string
mov edx, len ;length of string
mov ebx, 1 ;STDOUT
mov eax, 4 ;system call number to write output to screen
int 0x80

mov eax, 1 ;system call number to quit program
int 0x80

section .data

msg db "Hello! This is 32-bit Linux program.",10
len equ $ - msg


Run online at https://jdoodle.com/ia/tOY

Example output:

user posted image

To note difference between Linux x86 and Linux x64 system programming is that, 32-bit uses "int 0x80" whereas 64-bit uses "syscall" to call the kernel. Please correct me if I am wrong.

This post has been edited by FlierMate1: Aug 11 2022, 05:43 PM
angch
post Aug 12 2022, 09:45 AM

On my way
****
Junior Member
631 posts

Joined: Jul 2006
You got it. (re: 64 bit and syscall)

https://jameshfisher.com/2018/03/10/linux-a...ly-hello-world/

This post has been edited by angch: Aug 12 2022, 09:45 AM
MatQuasar
post Nov 4 2023, 05:20 PM

Getting Started
**
Junior Member
248 posts

Joined: Jun 2023
QUOTE(FlierMate @ Jul 24 2021, 10:29 PM)
UPDATE:
Here's another code for displaying the basic CPU info:

Two most common value returned are:
* "AuthenticAMD" – AMD
* "GenuineIntel" – Intel
*
user posted image

cpubrand.zip contains cpubrand.asm (Source code) and cpubrand.exe (32-bit Windows CLI program) to return 12-char CPU brand string.

user posted image

This post has been edited by MatQuasar: Nov 4 2023, 10:13 PM


Attached File(s)
Attached File  cpubrand.zip ( 36.79k ) Number of downloads: 3
xboxrockers
post Nov 13 2023, 06:43 AM

On my way
****
Senior Member
661 posts

Joined: Dec 2011




Cool I've been tinkering with buildroot, fun to see you are exploring sys programming in Linux.

 

Change to:
| Lo-Fi Version
0.0134sec    1.07    6 queries    GZIP Disabled
Time is now: 9th December 2023 - 10:43 PM