Egyéb: Assembly, Ada...

Rendszerindítás Minix3 Fájlrendszerről

https://gitlab.com/bztsrc/minix3fs

Egyszer csak tele lett a tököm, hogy mindenki a FAT-tel szív, amikor van sokkal egyszerűbb és jobb alternatíva, ezért valamikor régen összeraktam egy részletes leírást példakódokkal a Minix3 Fájlrendszerről. Már el is feledkeztem róla, de emiatt most valaki megkeresett és megkérdezte, hogyan lehet bootolni róla (mivel a Minix3 a NetBSD boot loaderét használja, ami szörnyű és nem igazán felhasználóbarát, a neten található összes bootszektor példa meg csak FAT-et tud). Szóval jogos volt a kérdés, nyilván egyik meglévő példa sem tud fájlokat betölteni MFS-ről.

Ezért úgy döntöttem, hozzáadok egy MFS bootszektor példakódot a repómhoz, ami Assembly-ben lett írva. Ez képes
- betölteni egy tetszőleges fájlt (kernelt vagy második lépcsős betöltőt) a Minix3 Fájlrendszerről,
- autodetektálja a formátumát (ELF, PE/COFF, a.out),
- parszeolja, betölti a szegmenseit és
- beállítja a neki megfelelő környezetet (protected mode vagy long mode).
Mivel ilyen okos, ezért ez a betöltendő futtatható már bármilyen magas nyelvből (C, Ada, Rust, Go, stb.) fordítható, nem szükséges az Assembly ehhez már.

A bootszektor forrását telepakoltam kommentekkel, de ha valakinek kérdése van, vagy talált egy bugot, akkor szóljon!

A repóban egyébként található egy függőségmentes, multiplatform mfsboot parancs is, ami képes telepíteni ezt a bootszektort egy Minix3 Fájlrendszer szuperblokkba. A betöltőnek nincs több komponense, mindössze a bootszektorból áll.

kicsi assembly meg gdb bénázás

Ifjoncabb kollégákkal beszélgetve szóba került, hogy még nem láttak assembly kódot, ezért gondoltam mutatok nekik, mégiscsak tudják mi fán terem :)

 

Az volt az ötletem, hogy nézzünk meg egy HelloWorldöt asm-ben meg javaban, hogy lássák tényleg ilyen ilyen obskúrus izék lesznek abból amit ők írkálnak. Na a Javaról hamar letettem, hogy gdb-vel nézegessek egy System.out.println() -t, próbáljuk meg C-ben, de itt is ráballagtam a banánhéjra.

 

Az asm progi:

.global _start

.text

_start:
	mov $1, %rax
	mov $1, %rdi
	mov $message, %rsi
	mov $13, %rdx
	syscall

	mov $60, %rax
	xor %rdi, %rdi
	syscall

.data

message:
	.ascii "Hello World!\n"

 

A C progi:

#include <stdio.h>

int main(void) {
	puts("Hello World!\n");
	return 0;
}

gcc -Wall -g hello.c -o helloc

 

gdb helloc

 

aztán breakpoint a puts-ra és had szaladjon!

...

Reading symbols from helloc...
(gdb) b puts
Breakpoint 1 at 0x1050
(gdb) r
Starting program: /sandbox/asm/helloc 

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) 
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, __GI__IO_puts (str=0x555555556004 "Hello World!\n") at ./libio/ioputs.c:33
33	./libio/ioputs.c: No such file or directory.
(gdb) disassemble
Dump of assembler code for function __GI__IO_puts:
Address range 0x7ffff7c7af40 to 0x7ffff7c7b166:
=> 0x00007ffff7c7af40 <+0>:	endbr64
   0x00007ffff7c7af44 <+4>:	push   %r14
   0x00007ffff7c7af46 <+6>:	push   %r13
   0x00007ffff7c7af48 <+8>:	push   %r12
   0x00007ffff7c7af4a <+10>:	push   %rbp
   0x00007ffff7c7af4b <+11>:	mov    %rdi,%rbp
   0x00007ffff7c7af4e <+14>:	push   %rbx
   0x00007ffff7c7af4f <+15>:	sub    $0x10,%rsp
   0x00007ffff7c7af53 <+19>:	call   0x7ffff7c224c0 <*ABS*+0xa6ff0@plt>
   0x00007ffff7c7af58 <+24>:	mov    0x17aec1(%rip),%r13        # 0x7ffff7df5e20
   0x00007ffff7c7af5f <+31>:	mov    %rax,%rbx
   0x00007ffff7c7af62 <+34>:	mov    0x0(%r13),%r12
   0x00007ffff7c7af66 <+38>:	testl  $0x8000,(%r12)
   0x00007ffff7c7af6e <+46>:	je     0x7ffff7c7b040 <__GI__IO_puts+256>
   0x00007ffff7c7af74 <+52>:	mov    %r12,%rdi
   0x00007ffff7c7af77 <+55>:	mov    0xc0(%rdi),%eax
   0x00007ffff7c7af7d <+61>:	test   %eax,%eax
   0x00007ffff7c7af7f <+63>:	jne    0x7ffff7c7b096 <__GI__IO_puts+342>
   0x00007ffff7c7af85 <+69>:	movl   $0xffffffff,0xc0(%rdi)
   0x00007ffff7c7af8f <+79>:	mov    0xd8(%rdi),%r14
   0x00007ffff7c7af96 <+86>:	lea    0x177d63(%rip),%rdx        # 0x7ffff7df2d00 <_IO_printf_buffer_as_file_jumps>

...

 

Nyilván van a glibc-ben egy csomó más fontos sallang is, de azt furcsállom, hogy egy darab kernel hívás (syscall vagy call 0x80) nincs benne. Persze máshol biztos van, csak így, hogy kb. 0 az átfedés a két kód között, nem túl szemléletes :)

 

Segítsetek kérlek mit, hogy írjak másként, hogy összehasonlítható legyen?

 

Köszi!

Doom kvantumszámítógépen

Mint tudjuk, a Doom mindenen elfut, és most már kvantumszámítógépen is:

https://github.com/Lumorti/Quandoom

Vagyis hát csak futna, mert ehhez 72 000 qubitre és 7 000 logikai qubitre lenne szükség. A jelenlegi legfejlettebb kvantumszámítógép 1180 qubites és 48 logikai qubittel rendelkezik, így tehát még ici-picit odébb van az ezt futtatni is képes hardver.

De emulátorban legalább már kipróbálható (amit direkt ehhez az egy Doom QASM fájlhoz írtak, más programot nem is tud futtatni).

[ Elkerülve ] A manóba! Kódszegmens konvertálása ELF formátumra

Van egy régi linux bináris programom - sajnos forrás nélkül -, ami elvileg régen futott linux alatt. Ma nem fut, mert nem megfelelő formátumú. Tippre, ez a programnak csak a kódszegmens része. (Régen tanultam már az x86 assemblyt, és azóta sem használtam, így gyakorlatilag nulláról indulok.)

Egyetlen érdemi támpontot találtam a neten, miszerint az "objdump" segítségével előállítható belőle az assembly forrás, amit már könnyedén ELF formátumra lehetne fordítani.

Addig eljutottam, hogy az objdump képes belőle assembly szerű forrást készíteni, de nem tiszta assembly kódot, így tovább kell konvertálni ezt a forrást. Egyelőre nem sikerült olyan assembly forrás generálnom az objdump kimenetéből, amit egy assembler le is fordítana.

Ha valakinek van ötlete, hogyan lehetne egy régen futó linux bináris újra futtathatóvá tenni, ne tartsa magában. Minden támpontnak örülnék.

----------------------------

Megoldás helyett meglett a forrás. Köszönöm a segítségeket.

MS-DOS emulálás, com port megfigyelés

Sziasztok!

Van egy kb. 30 éves program amit próbáltam virtualbox, és vmware alatt is futtatni. A hostra még feltelepítettem a com0com virtuális port emulátort. (putty segítéségével látom is hogy COM1 tükröz COM2 re, oda vissza, gépelgettem terminálablakban). Emulált Windows al is kipróbáltam, hogy a hozzáadott com1 et látom a host gép com2 portján.

A problémám, hogy a futtatót dos alapú program kommunikációját sehogy nem látom. Probáltam COM1 sé COM2 paraméterrel. A programban nem sok az infó.

Hogyan tudnám elfogni virtuális gépben???

 

 

MS-DOS UMA

Egyébbe tettem jobb ötlet híján, retro kérdés következik :)

A kérdésem túl régi és túl specifikus, vagy az is lehet hogy egész egyszerűen nem látom a fától az erdőt, de talán valaki tud segíteni és fényt hozni.

Az eredetileg (és valós módban utána is) 20 bites címzéssel rendelkező x86 processzorok, jelen esetben a 8088 és 8086ra gondolok, műkődképesek DOS 1.0 - DOS 6.22 rendszer mindegyikével. Az 1 megabyteos eredeti memória klasszikus felosztása hogy van a Conventional Memory, ami 0-640K (10x64K - ez mindenre elég, világos), aztán van az UMA, az Upper Memory Area, ami 384k méretű és elvileg mindig ennyi és mindig ott (?) (640K-1024K). Verziótól függően ebben lehet TSR, DEVICE, de még a DOS egy része is.

A kérdésem az, hogy mi van azokban az esetekben, amikor 1MB-nál kevesebb volt az elérhető RAM? többek közt volt 128K, 384K, 512K, 640K méretű kiszerelés is az IBM PCből. Ilyenkor hol van vagy hogy értelmezendő az UMA?  

Raytracer a boot szektorban

Fény útjának modellezése 3D-s kép rendereléséhez, mindez kevesebb, mint 512 bájtban. Ugyanaz az Oscar Toledo követte el, akinek a világ legkissebb sakkprogramját is köszönhetjük (ami természetesen C-ben íródott és IOCCC nyertes ;-) ).

A raytracker forrása és qemu-ban indítható binárisa elérhető itt:
https://github.com/nanochess/RayTracer

Mint bármelyik boot szektor, Assembly-ben íródott és csak valós módú utasításokat használ, ezért MS-DOS .com programnak is lefordítható. A fordításhoz a Netwide Assembler szükséges.
A megjelenítés érdekessége, hogy palettás módot használ, mindössze 256 színnel (azaz fix színekkel dolgozik, nincs true color mixing).

Korábban csinált már raycasting-ot is boot szektorban (az, amire a Doom is épül, nem azonos a raytracinggel).
https://en.wikipedia.org/wiki/Ray_casting
https://en.wikipedia.org/wiki/Ray_tracing_(graphics)

Bár sok értelme nincs, mégis hatalmas pacsi Oscar-nak! Na, ő az igazi szent őrült, nem én :-)

Programozási versenyfelhívás

Elegem lett a sok nagyszájúból, ezért úgy döntöttem, lehetőséget adok nektek a gyakorlatban is bizonyítani, és egy versenyre hívlak ki Titeket!

Amennyiben nem érkezne egyetlen működőképes beadvány sem, vagy a C nyerne, akkor azt úgy kell érteni, hogy valójában a gyakorlatban egyik csodanyelv sem képes leváltani a C-t, és továbbiakban nem hangoztathatjátok ezt a HUP-on. Ha nem a C nyerne, akkor pedig vice versa, megígérem, hogy nem fogom a továbbiakban az orrotok alá dörgölni, hogy felültetek a hypenak és bedőltetek a marketing bullshitnek. Ez így fair, nem?

https://gitlab.com/bztsrc/langcontest

A feladat: egy olyan rendszerprogram írása, ami nem csinál mást, mint másodpercenként eggyel növel egy számlálót a képernyőn. Elég egyszerű, nem lehet probléma bármilyen nyelven megírni ezt, igaz?

A verseny szabályait igyekeztem úgy kialakítani, hogy azok a lehető legegyenlőbb feltételeket biztosítsák, bármilyen nyelvről és fordítóról is lett légyen szó, és igazságos összehasonlítási alapot szolgáltassanak:

- architektúrának a 64 bites x86-ot választom, mert arra minden nyelvhez biztos van fordító és könnyedén tesztelhető, ráadásul tele van hozzá doksival a net
- mivel nincs oprendszer, a betöltőt biztosítom, emiatt nem kell aggódni, nektek csak egyetlen lefordított rendszerprogramot kell csinálni
- bármilyen nyelv használható, az Assembly-t leszámítva (a betöltő teszteléséhez egy Assembly-ben írt referencia implementációt biztosítok)
- inline Assembly nem, csak az adott nyelv natív utasításkészlete használható, a forrásnak hordozhatónak kell lennie (azaz hiba nélkül le kell fordulnia többféle architektúrán, akkor is, ha úgysem működne ott)
- nem használható semmi olyan kulcsszó vagy opció, ami kikapcsolja a nyelv alap funkcióit, mert az úgy már nem a csodanyelv lenne (pl Rust-ban az unsafe/unmanaged, vagy C++ alatt az -fno-exceptions/-fno-rtti nem megendegett)
- bármilyen más kulcsszó, parancssori opció használható, akár fordítóspecifikus, architektúraspecifikus is (például hívási, optimalizálási, ellenőrzési, kódgenerálási, linkelési stb., bármi más mehet, csak a nyelv alapkészletét tilos leszűkíteni)
- bármilyen fordító megengedett, ami képes az adott nyelvet lefordítani (például Go esetén gcc-go/golang, C esetén gcc/Clang stb., semmilyen megkötés nincs a fordítóra)
- bármilyen szabványos függvénykönyvtár használható, ami a nyelvvel és a fordító telepítésével együtt érkezik vagy Ti írjátok, de harmadik féltől származó, netről letöltött nem (ha a nyelvnek van bare metal változata, természetesen azt is ér használni)
- bármilyen fordítási segédprogram megengedett, olyan is, amit külön kell telepíteni vagy saját fejlesztésű (például interface bindolók, fejléc generálók, linker szkriptek, binutils, make/mk/cmake/ant/scons/meson/ninja/azanyjakinyja stb.)
- a lefordított program nem lehet nagyobb, mint amit egyetlen BIOS hívással be lehet tölteni a lemezről (65024 bájt)
- a képernyőre VGA teletype módban kell írni (ASCII karakter (0x30 - 0x39) + attribútum (0x07 fehér) párosokból álló tömb a 0xB8000 fizikai címen a Video RAM-ban)
- a pollozás nem megengedett, mert az nem lenne sem hatékony, sem energiatakarékos, sem pontos
- a program megírására 1 hónap áll rendelkezésre
- egy program többször is módosítható és többször is beadható ez idő alatt, a legutolsó fog számítani (lehet reagálni a mások által beadott pályaművekre, és lehet újabb optimalizációkkal előrukkolni)
- a nyertes az a program, ami a legkevesebb segédprogramot, kulcsszót és specifikus opciót használja az adott nyelv készletéből (magyarán ami a legkevésbé gányolt), ezen kívül pedig ami legkissebb bájtméretű, működő binárist produkálja, holtverseny esetén meg ami a kevesebb memóriát fogyasztja futás időben (vermet is beleértve)

A felsorolt limitációk a hardveres futási környezet sajátosságai (long mód, BIOS betöltés, VGA képernyő), ezek nem megkerülhetőek, muszáj alkalmazkodni hozzájuk.
Elvileg a 64 bites long mód nem tartozna ide, de ennélkül már a verseny indulása előtt nyerne a C és elvérezne az összes többi csodanyelv... :P De jófej leszek és esélyt adok nektek, így legyen hát 64 bit only.

A függvénykönyvtárakra vonatkozó megkötés azért került bele, hogy csak a nyelv maga számítson. Standard lib használható, de el is hagyható, 3rd party lib viszont tilos, mert az már nem a nyelv része.

Hogy a fordítási környezetből adódó eltéréseket is kiiktassuk, két betöltőt is biztosítok: az első ELF binárist tölt be, és SysV ABI-t használ:

cat boot_elf.bin programod.elf > disk.img

A másik pedig PE/COFF binárist és MS fastcall ABI-t (pont, mint az UEFI):

cat boot_pe.bin programod.exe > disk.img

Mindkét esetben az elkészült virtuális lemezt qemu alatt, a következő paranccsal kell tudni futtatni:

qemu-system-x86_64 disk.img

Hogy a programokba tényleg ne kelljen Assembly betét, a betöltő a bináris fejlécében megadott linkcímekre másolja a szegmenseket, kinullázza a bss-t, beállítja a vermet lefele növekvően 640K-ra, az alacsonyszintű CPU utasításokhoz pedig interfészt és wrapper függvényeket biztosít, mielőtt a belépési pontot meghívná.
Relokációt nem végez, a programot linkeljétek valaholva a 96K és 640K vagy az 1M és 2M közé, ahová jólesik, és több szegmensből is állhat akár.

Az interfészt pontosan ugyanúgy kell használni, mint UEFI esetén, csak itt más függvényeket tartalmaz. Ennek a C nyelvű definíciója:

typedef struct {
  void (*load_idt)(const void *buffer, const uint16_t size);  /* betölti a megszakításkezelőket */
  void (*enable_interrupts)(void);                            /* engedélyezi a megszakításokat */
  void (*disable_interrupts)(void);                           /* letiltja a megszakításokat */
  void (*iretq)(const int localsize);                         /* visszatér a megszakításkezelőből */
} almost_efi_system_table_but_not_quite_t;

A program belépési pontja egy mutatót kap paraméterül erre a struktúrára, pontosan úgy, mint UEFI-nél.
EDIT: mivel sokan sírtatok, ezért módosítás: az összes paraméternél kiírtam, hogy const, ha ez nem lett volna egyértelmű, és ezeknél a függvényeknél, és szigorúan csakis ezeknél az interfész által biztosított függvényeknél használható Rust alatt az unsafe. VAGY Az interfészt egyáltalán nem kötelező használni, le is implementálhatjátok ezt a négy függvényt Rust-ban, ekkor azonban nem lesz külsős függvényhívás, így ilyenkor tilos az unsafe.

Továbbá, hogy még a hardverprogramozási készségek se számítsanak, és tényleg csak a nyelveket mérjük össze, a betöltő megteszi azt a szívességet is, hogy előre felprogramozza a megszakításvezérlőt valamint a PIT-et másodpercenkénti 100 IRQ megszakításra, azonban nem kezd megszakításokat generálni, míg az enable_interrupts() függvényt meg nem hívjátok.
Hasonlóan az iretq() hívás gondoskodik a megszakításvezérlőben az IRQ nyugtázásáról is, így azzal sem kell törődnötök. A load_idt() híváshoz segítségként, 32 kivételfajta van és 16 IRQ, a kódszelektor a 32-es, a megszakításkapu attribútuma meg a 0x8E.

Itt az alkalom, hogy bizonyítsátok, a Go, Rust vagy bármelyik másik agyonhypeolt csodanyelv valóban képes lehet a C leváltására! Én állítom, hogy nem, bizonyítsátok be, hogy tévedek! Versenyre fel!

Wise díjak, banki költségcsökkentés

Üdv!

Érdekelne, ha valaki használ-e itt wise-ot, milyen díjak merülhetnek fel használat közben. Nézegettem az oldalukat, de maradt bennem egy kérdés. Ha HUF számláról HUF-ra utalnék annak mi a díja?

Illetve kártyás fizetés hogyan megy?

Létezik virtuális kártya is, hogy pl. NFC-s telefonnal lehessen fizetni, vagy mindenképpen kell fizikai kártya amit aztán hozzá tudok adni pl. Google Pay-hez?

 

Az Erste betéti kártyájától akarok megszabadulni, mert lassan ott tartunk, hogy évi 10 rugó.

Ha jól működne, akkor átdobom a gubát wise-ra, erstének meg visszaadom a kártyát. Egyék meg.
A hitelkártya még egyelőre fenntartható költségekkel üzemel, de nem sokat fogok rajta évente szerintem. Ezt is újra kell számolnom majd.

 

Már régebb óta gondolkodom a dolgon, de az apropót most ez a cikk adta.

[megoldva] AVR architektura, feltetelben

Azt hogyan tudom ellenorizni egy AVR assembly forraskodban, `avr-as` segitsegevel forditvan hogy milyen architekturara is forditjuk? Peldaul: `avr-as -mmcu=avr31 -o xyz.o xyz.s` es akkor a *.s-ben meg ilyesmik lennenek, mint:

.if (avr3 | avr31 | avr5)
.set SOMETHING, 8
.else
.set SOMETHING, 4
.endif

Es akkor ezen fenti parancsnal a SOMETHING erteke 8 legyen merthogy AVR31-es az architektura. Szoval mit is irjak az elso `.if ...` sor helyere ha epp a fenti architekturakra gondol a kolto... Konkretan ezalapjan probalkoztam, meg az itt elpottyintett avr-as understands the same -mmcu= options as avr-gcc mondat alapjan biztam benne hogy egy `.if (AVR_ARCH == 31)` pl jo lehet, de sajnos nem :/

Koszi, A.