Recent Posts

Pages: 1 2 [3] 4 5 ... 10
21
Programming with NASM / Re: Linux 64bit / Threads
« Last post by andyz74 on January 25, 2024, 08:31:24 PM »
OK, I've tested your code and it runs nicely.  :-)

But to be honest, I think, my intended question is still open. (Waiting at each other of the processes...)

Maybe I should explain a little better : I have modified this code to calculate primes.  Let's say, i want to test the number 2000 to be a prime:
So I divided 2000 by 2 ( got 1000 )  and
tell the parent process to divide the 2000 through all numbers between 2 and 1000,  and
tell the child process to divide the 2000 through all numbers between 1000 and 2000.

I know, the range can easily be decreased from 2 to sqrt(number) but I do it like this for testing the fork-thing.

If the parent-process, or the child-process sees a division which goes out even, some boolean-like variable like "not_a_prime" should be set to 1 and both processes could be stopped. Otherwise it is a prime.
22
Programming with NASM / Re: Linux 64bit / Threads
« Last post by fredericopissarra on January 25, 2024, 08:48:30 AM »
There are no 'threads' here, but different processes...
Here's a better implementation for your forking...

Code: [Select]
; fork,asn
;
; nasm -f elf64 -o fork.o fork.asm
; ld -s fork.o -o fork
; ./fork
 
  bits 64
  default rel     ; All offset only effective addresses are rip-relative from now on...
 
  ; Since no data will be writen, they can be at .rodata section.
  section .rodata

  ; We don't need the nul char!
childMsg  db  `This is the child process\n`   ; a message string
clength   equ $-childMsg
parentMsg db  `This is the parent process\n`  ; a message string
plength   equ $-parentMsg

tspec:
  dq  3                                       ; 3 seconds delay.
  dq  0
 
  section .text

  global  _start
 
_start:
  ; Notice: Using RAX here will encode a 10 bytes instruction (rex prefix, 8 bytes for the immediate and the opcode).
  ;         In x86-64 mode, changing E?? will AUTOMATICALLY zero the upper 32 bits of R?? registers.
  mov   eax,57              ; sys_fork
  syscall
 
  ; fork() will return a file descriptor (int type).
  test  eax,eax
  js    .fail               ; sys_fork can fail (returs a descriptor < 0).
  jz    .child
 
  ; Parent process.
  mov   eax,1               ; sys_write
  mov   edi,eax             ; stdout
  lea   rsi,[parentMsg]     ; Must be rip-relative addressing.
  mov   edx,plength
  syscall
 
  call workalot
 
.exit:
  mov   eax,60
  xor   edi,edi
  syscall
 
.fail:
  mov   eax,60
  mov   edi,1
  syscall
 
  align 4
.child:
  mov   eax,1           ; sys_write
  mov   edi,eax         ; stdout
  lea   rsi,[childMsg]  ; message address (rip-relative)
  mov   edx,clength     ; message string length
  syscall
 
  call workalot
  jmp .exit

; -------- unten nur proceduren ---------------------
  align 4
workalot:
  mov   eax,35        ; sys_nanosleep
  lea   rdi,[tspec]
  xor   esi,esi
  syscall
  ret
23
Programming with NASM / Linux 64bit / Threads
« Last post by andyz74 on January 24, 2024, 05:38:14 PM »
Hi !
I'm just playing around with learning about threads.  Somewhere in the internet I found a little example and changed it for my mind and it seems to work correct for now.

Code: [Select]
; Fork
; nasm -f elf64
; ld fork.o -o fork
; Run with: ./fork
 
[bits 64]
 
SECTION .data
childMsg        db      'This is the child process', 0h     ; a message string
clength equ $-childMsg
parentMsg       db      'This is the parent process', 0h    ; a message string
plength equ $-parentMsg
crlf db 0xA,0xD ; newline, length is 2
 
SECTION .text
global  _start
 
_start:
 
    mov     rax, 57              ; SYS_FORK
    syscall
 
    cmp     rax, 0              ; if eax is zero we are in the child process
    jz      child               ; jump if eax is zero to child label
 
parent:

mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
mov rsi, parentMsg ; message address
mov rdx, plength ; message string length
syscall

mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
mov rsi, crlf ; message address
mov rdx, 2 ; message string length
syscall

call workalot

jmp exit
 
 
child:


mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
mov rsi, childMsg ; message address
mov rdx, clength ; message string length
syscall

mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
mov rsi, crlf ; message address
mov rdx, 2 ; message string length
syscall

call workalot

jmp exit


exit:
mov rax, 60 ; sys_exit
mov rdi, 0 ; return 0 (success)
syscall

; -------- unten nur proceduren ---------------------

workalot:
mov rcx, 65000
loop1:
push rcx

mov rcx, 65000
loop2:
push rcx
nop
pop rcx
loop loop2

pop rcx
loop loop1
ret


As you see, it just throws out two little messages in a fork and runs down a delay and stops.

Now, my question is, if I have dependencies in the threads at each other, maybe some calculations with needed sums at the end, than I have to wait for this.
I know, there exists something called
"SYSCALL_WAIT4"
but to be honest, I don't have a clue, how to realize that. :-/

Does anyone habe a nice example or can explain a little bit?

Greetings, Andy :-)
24
I may have missed 32 vs 64 bit sytm calls...

Best,
Ftank

25
They were both two different sources of the same port library. The first was creating input for a file and the second was for reading output to a file. Could you figure it out or did you need something else?
26
  ; open the file
    mov eax, 2 ; sys_open

My menory' s all  shot. Is this right?

2 fork 5 open ?

Best,
Frank

27
Greetings everyone
 I am moving from my most recent post to discuss a new block in the standard library code. There is an apparent deficiency in regards to the afore mentioned read and write calls. Here I have a simple boot and two different instances (from distinct sources) both not yielding any effect.


Code: [Select]
section .data
;    pathname dd "/home/Documents/Platforms/Programs/Sources/referenceA2023/Concepts/Codec/DesignII/Test/Base/new.text"

;    pathname dd "/home/chris-deb-auth/Documents/Platforms/Programs/Sources/A2024/small_rebuild/new.txt"
;    toWrite dd "test text here",0AH,0DH,"$"
;   length equ $ - toWrite

    filename db "new.txt", 0 ; filename with null terminator
    toWrite dd "test text here",10
 ;   message db "Hello, world!", 10 ; message with newline
 ;   msglen equ $ - message ; length of message
   length equ $ - toWrite


section .text

global Filer

Filer:
    ; open the file
    mov eax, 2 ; sys_open
;    mov ebx, pathname ; pointer to filename
    mov ebx, filename ; pointer to filename
    mov ecx, 0x201 ; O_WRONLY|O_CREAT
    mov edx, 0x1b6 ; 0644
    int 0x80 ; call kernel
    mov esi, eax ; save file descriptor

    ; write to the file
    mov eax, 4 ; sys_write
    mov ebx, esi ; file descriptor
    mov ecx, toWrite ; pointer to message
    mov edx, length ; length of message
    int 0x80 ; call kernel

    ; close the file
    mov eax, 6 ; sys_close
    mov ebx, esi ; file descriptor
    int 0x80 ; call kernel

    ; exit the program
    mov eax, 1 ; sys_exit
    mov ebx, 0 ; exit code
    int 0x80 ; call kernel


jmp $


times 510 - ($-($$)) db 0
db 0x55,0xaa


Code: [Select]
section .data
;    pathname dd "~/.../new.text"

   pathname dd "new.txt"
   toWrite dd "test text here",0AH,0DH,"$"
   length equ $ - toWrite



section .text

global Filer

Filer:
;section .data
;    pathname dd "/home/Documents/Platforms/Programs/Sources/referenceA2023/Concepts/Codec/DesignII/Test/Base/new.text"
;    toWrite dd "test text here",0AH,0DH,"$"
 

    mov eax,5
    mov ebx,pathname
    mov ecx,101o
    mov edx,700o
    int 80h

    mov ebx,eax
    mov eax,4
    mov ecx,toWrite
    mov edx,17

;    mov edx,length
    int 80h


jmp $


times 510 - ($-($$)) db 0
db 0x55,0xaa


I''m trying to understand each of these instances but if I can't get a yield I really don't have any clue. If anyone else has been through this library I could really use whatever can get through this.

Cheers and Regards
28
Good day everyone,

I'm happy to make a return of another contribtion to the community. Here I had a steady state protected mode program for simple scanning data functions. The goal was to make an auxiliary compiler for novice enthusiastic (like myself haha) for parsing things like data values and word processing.

This post is showing the design state where I'm trying to add a read file function right beside the scan functions. Curiously I couldn't get the buffer values to reserve when I run beside the scan code so I tried adding a standard task state to check in the larger state machine. Here the yield is getting me mixed results when tracking the values between states. I found that keeping track of values in the standard datapipes has te closest result so I left the value in cx to (mov) into the pre-protected mode state. Here however is where I get mixed results because when  I check the (cmp) gate to move to the new module it just falls through it without the logic!

I wanted to post a copy of this for review so I'm posting each part step by step and add the full reference for anyone else intrigued by this prospect.

First area is the stack functions for cmd_buffer given by cmd_prompt1 and the reference function given by cmd_prompt1.A
Code: [Select]
cmd_prompt1:

call Heap_Buffer
call Encoder

; call Paging

; call Filer

mov byte [Ref_CountA],0
call Parser.Blank

call Parser.Signature_Scan
call Parser.Assignment


call Decoder



call cmp_delta

;task segment prep code
.A:
;push cs
;push .A
push .B

pop word [Ref_Task_1]
;pop cx
;mov word [Ref_Task_1],cx


;call Domain.TaskA
jmp Domain.TaskA

.B:
jmp cmd_buffer

;qqqqqqqqqqq
;native test code skip

;task prep code area

.TaskA:
jmp poll_function




simple prep area gate for return tasking

Code: [Select]
; prep area
; prep area
Ref_Task1: dw 0

;protectedGate1:

;qqqqqqqqqqqq

;preset code

;task segment preset


mov word [Ref_Task1],cx
;cmp word [Ref_Task1],0
cmp cx,0
jz short protectedGate1





jmp TaskA

;qqqqqqqqqqqqq

protectedGate1:

mov si,String
call cmdprint


cld
cli

in al,0x92
or al,2
out 0x92,al

lgdt[gdt32Ptr]
lidt[IdtPipe]

mov eax, cr0
or eax,1
mov cr0, eax

; mov [saved_segment],ds

jmp code32_post:__protected_mode_32


%include 'file_system.inc'


TaskA:

cmp cx,0
jz protectedGate1


call Filer

jmp protectedGate1



.inc file for the read file test
Code: [Select]

;section .data
file db "text.txt",0

;section .bss

;test values
;referencer resb 4
;buffer  resb 1024

;referencer db 4
;buffer  db 1024
;buffer  db 100


;len     equ 1024
len     equ 100

;
;
;section .text

global Filer

Filer:
    mov eax,5
    mov ebx,file
    mov ecx,0
    int 80h

    mov [referencer],eax
; read presets

    mov eax,3
    mov ebx,[referencer]   
    mov ecx,buffer   ;read to buffer
    mov edx,len      ;
    int 80h         ;read len db to buffer

    mov edx,eax       ;puts data counted

; write presets
    mov eax,4        ;write preset
    mov ebx,1        ;to primary stream
    mov ecx,buffer   ;from primary buffer
    int 80h         ;reserve all read scanned data from buffer


    mov eax,6        ;close file preset
    mov ebx,[referencer]       ;
    int 80h         ;


    mov eax,1
    mov ebx,0
    int 80h         


ret


Pseudocode proof-of-concept on scan

Code: [Select]
int data1 = 12 _ int data2 = 23 _

check the page.Main values for yield


Summary
Currently I'm trying to debug this as native code. While I have experience with debuggers like gdb I sometimes run into unknowns such as when data segments jump outside of expected values in this case file_system.inc . If anyone else would like an explanation of my debug settings please let me know so I can clarify further testing.



Notice 1-
I got the machine steady but still not stable. the new file instructions stall when I (cmp) pass by exact value instead of reference. What's more curious is according to my gdb now the jump @ cmp goes into the 512 boot segment.

Code: [Select]
;    ReTimerOS
;    Copyright (C) 2022,2023  Christopher Hoy
;
; This file is part of ReTimerOS
;    ReTimerOS is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <https://www.gnu.org/licenses/>.



;%define REBASE_ADDRESS(A)  (0x7E00 + ((A) - protectedGate1))

%define BUILD_GDT_DESC(bounds,base,access,flags) \
((( base & 0x00FFFFFF) << 16) | \
(( base & 0xFF000000) << 32) | \
( bounds & 0x0000FFFF) | \
(( bounds & 0x000F0000) << 32) | \
(( access & 0xFF) << 40) | \
(( flags & 0x0F) << 52))

;[ORG 0x7E00]

[BITS 16]



;section .text

; prep area
Ref_Task1: dw 0

;protectedGate1:

;qqqqqqqqqqqq

;preset code

;task segment preset


mov word [Ref_Task1],cx
;cmp word [Ref_Task1],0

;cmp cx,0
;jz short protectedGate1
cmp cx,0x8b76
jz TaskA



;jmp TaskA

;qqqqqqqqqqqqq

protectedGate1:

mov si,String
call cmdprint


cld
cli

in al,0x92
or al,2
out 0x92,al

lgdt[gdt32Ptr]
lidt[IdtPipe]

mov eax, cr0
or eax,1
mov cr0, eax

; mov [saved_segment],ds

jmp code32_post:__protected_mode_32


%include 'file_system.inc'


TaskA:

cmp cx,0
jz protectedGate1


call Filer

jmp protectedGate1




cmdprint:
cld
mov ah,0x0E

cmdstring:
lodsb
int 0x10
cmp al,0
jnz cmdstring
ret






;section .text

[bits 32]
; 32 bit protected mode
__protected_mode_32:use32
;    mov ax, 0x10
mov ax,data32_post
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
;    mov ss, ax
    ; restate cr3
    mov cr3, ebx
    ; restate esp
    mov esp, edx

mov cx,[gate_voucher]
cmp word [gate_voucher],0
jnz loopcheck
mov word [gate_voucher],1


jmp BIOS32_PREP


loopcheck:
hlt
jmp loopcheck

; jmp 0x8000

BIOS32_PREP:use32


;    pusha
    ;pushf
    ; save current esp to edx
    mov edx, esp
    ; jumping to 16 bit protected mode
    ; disable interrupts
    cli
    ; clear cr3 by saving cr3 data in ebx register
    xor ecx, ecx
    mov ebx, cr3
    mov cr3, ecx

jmp code16_post:__protected_mode_16

[bits 16]
; 16 bit protected mode
__protected_mode_16:use16
    ; jumping to 16 bit real mode

xor eax,eax
xor ecx,ecx

;   mov ax, 0x38
mov cx,data16_post

; mov ax,0

    mov ds, cx
    mov es, cx
    mov fs, cx
    mov gs, cx
    mov ss, cx
    ; turn off protected mode
    ; set bit 0 to 0

;tss prep
mov bp,word [Ref_Task1]


    mov eax, cr0
    and al,  ~0x01
    mov cr0, eax

; jmp 0x0:REBASE_ADDRESS(__real_mode_16)
; jmp 0x0:REBASE_ADDRESS(0x0000_9000)

jmp 0x8000
; jmp 0x9C00

; jmp 0x9e00

; jmp 0xa000

; jmp 0xc000

; jmp 0xee00

; jmp 0xf400

; jmp 0xf000


;section .data

String: db 'platform 2',10,13,0
checkString: db 'check',10,13,0


gdt32:
dq BUILD_GDT_DESC(0,0,0,0)
gdt32code:
dq BUILD_GDT_DESC(0x0000ffff,0,10011010b,1100b)
gdt32data:
dq BUILD_GDT_DESC(0x0000ffff,0,10010010b,1100b)
gdt16code:
dq BUILD_GDT_DESC(0x0000ffff,0,10011010b,1000b)
gdt16data:
dq BUILD_GDT_DESC(0x0000ffff,0,10010010b,1000b)


.stub1:

code32_post: equ gdt32code -gdt32
data32_post: equ gdt32data -gdt32
;.stub:
code16_post: equ gdt16code -gdt32
data16_post: equ gdt16data -gdt32

; tss32_post: equ gdt32tss -gdt32

gdt32Len: equ $-gdt32
gdt32Ptr: dw gdt32Len-1
dd gdt32


save_cr0 dd 0
save_cr3 dd 0
saved_segment resd 0
gate_voucher dw 0
saved_stack resw 0




IdtPipe:
dw 0x03ff
dd 0


referencer: times 4 db 4
buffer: times 100 db 1



times 512-($-$$) db 0

;%include 'gdt.inc'



Notice 2
I managed to get to the right task area when I push and pop the value but now I'm getting stuck on the call inside the task

Code: [Select]
push cx
pop bx


cmp cx,bx
jz TaskA


Notice 3
Had to fix the bound values to fit the file segments (1024->100) and currently testing the instruction segment sequences.
29
If you are curious, here's the implementation of sin() from glibc 2.31 source code: /sysdeps/ieee754/dbl-64/s_sin.c
30
A small measure of both methods: glibc (for x86-64) don't use fsin instruction (since SSE/SSE2 is the default means to use floating point):
Code: [Select]
; testfp.asm
  bits  64
  default rel

  section .text

  ; Since SSE don't have any 'transcendental' instructions we can use
  ; fp87 fsin, but the argument comes from XMM0 and the result is XMM0 as well.
  ; Using red zone here.

  global sin_
sin_:
  movsd   [rsp-8],xmm0

  fld     qword [rsp-8]
  fsin
  fstp    qword [rsp-8]

  movsd   xmm0,[rsp-8]
  ret
And the test code:
Code: [Select]
// test.c
#include <stdio.h>
#include <inttypes.h>
#include <math.h>
#include "cycle_counting.h"

extern double sin_( double );

int main( void )
{
  double a, s1, s2;
  counter_T c1, c2;
  unsigned int i;

  i = 0;
  c1 = c2 = 0;
  for ( a = 0.0; a < 2.0 * M_PI; a += M_PI / 180.0, i++ ) // dregrees to radians.
  {
    counter_T ctmp;

    ctmp = BEGIN_TSC();
    s1 = sin( a );          // glibc sin() function.
    ctmp = END_TSC( ctmp );
    c1 += ctmp;

    ctmp = BEGIN_TSC();
    s2 = sin_( a );         // our function.
    ctmp = END_TSC( ctmp );
    c2 += ctmp;

    // this is here 'cause without this the compiler will get rid of sin() call
    // since it is an 'intrinsic' and the result isn't used, otherwise.
    printf( "%g, %g\n", s1, s2 );
  }

  c1 /= i;
  c2 /= i;

  printf( "glibc sin(): %" PRIu64 " cycles.\n"
          "sin_():      %" PRIu64 " cycles.\n",
    c1, c2 );
}
BEGIN_TSC() and END_TSC() gets the timestamp counter, serializing the processor.
Sometimes sin_() is faster, but not always. Here's two results:
Code: [Select]
$ nasm -felf64 -o testfp.o testfp.asm
$ cc -O2 -ffast-math -c -o test.o test.c
$ cc -s -o test test.o testfp.o -lm
$ ./test
...
glibc sin(): 145 cycles.
sin_():      102 cycles.
...
$ ./test
...
glibc sin(): 174 cycles.
sin_():      210 cycles.
First case, sin_() is 29,6% faster than sin(). Second case, sin() is 17% faster than sin_().

So, to use fp87 instructions isn't a garantee of performance from hardware assisted complex functions.
Pages: 1 2 [3] 4 5 ... 10