It is currently Sun Aug 18, 2019 10:38 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: Mon Jul 08, 2019 11:06 pm 
Offline
Formerly Espozo
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3501
Location: Richmond, Virginia
I had been explicitly warned against making a GUI program in assembly, but (as I'm sure all of you already know,) I'm stubborn and thought it would make a fun exercise to make a simple window. I looked into how an X server works and read that you're supposed to establish a socket connection, so I looked up sockets and found this nice reference: http://www.cs.rpi.edu/~moorthy/Courses/ ... ocket.html

Since the program using the X Server should be a client, I saw that the only system calls I should have to use (other than "write" once I establish a connection) are "socket" and "connect". The socket syscall was simple enough to figure out; unless I'm understanding this incorrectly, this is all that has to be done:

Code:
   mov rdi, 0    ;domain AF_UNIX
   mov rsi, 1    ;type SOCK_STREAM
   mov rdx, 0    ;use default protocol (TCP)
   mov rax, 41   ;syscall number for socket
   syscall

Then, just like the "open" syscall, it returns a file descriptor in rax that you need to use for "connect" (and of course "write"). However, as lame as this is, I'm stuck at what the "socket address" (the structure pointed by rdi) is supposed to be in the "connect" syscall. I found this article https://www.ibm.com/support/knowledgece ... xsock.html that at least tells me what the address is supposed to look like (a unix filename) but I have no idea what it's supposed to be the filename of; the X Server itself?

This page I found goes over the X Window System protocol, but unsurprisingly, it expects that you already have a connection established. https://www.x.org/releases/X11R7.7/doc/ ... tion_Close



I get the feeling no one really does this stuff without using libraries... It's become apparent to me that there's really not much at all to be gained by using assembly over C here either; half of what I've been doing is just moving immediate values into registers, which a compiler will do just as well. Of course, that holds true for most programming now a days. :lol:


Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 1:00 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 4208
Location: A world gone mad
You will find the answer to your question in the details of your operating systems' man pages, specifically in section 2 which is for system calls. For example, here is connect(2) for Linux. Apologies if the man page link is invalid; you didn't specify what OS and/or distro you're using, so I am assuming Linux. If FreeBSD, here (edit: fixed link).

You will need to understand C to make heads/tails of this information, all the way down to understanding the format of the data structures, which usually means referring to actual system-wide [ttt]#include[/tt] files directly. All the man page documentation and "general-use documentation" you will find for syscalls will refer to using them in C; any higher-level PL is translating things into some C equivalent (usually the case) or compatible resulting binary code.

The x86 code you wrote I cannot verify/validate as I don't dig into syscall details at the x86 level often enough to verify, but I can tell you that AF_UNIX is a UNIX domain socket, which may or may not be what you want.

The details that you're looking for are in the sockaddr_un or sockaddr struct when combined with that particular socket type (AF_UNIX vs. AF_INET):

UNIX domain sockets refers to a specialised file-based socket on the same physical machine (and the server/thing you're connecting to has to support them + have one set up/listening). AF_UNIX with SOCK_STREAM is a UNIX domain socket using streams, while AF_UNIX with SOCK_DGRAM is a UNIX domain socket using datagrams. They behave differently. What's important is that AF_UNIX is not a TCP/IP socket; it's endpoint refers to an actual pathname in sockaddr_un structure member sun_path. You may also find unix(7) helpful for UNIX domain sockets (section 7 is a programmer's reference guide and is often neglected).

The client source code on the page you linked uses AF_INET (read: IP, as in Internet Protocol). AF_INET with SOCK_STREAM is a TCP socket, while AF_INET with SOCK_DGRAM is UDP. These refer a destination by IP address and port in the associated struct (note that the IP addresses are encoded in what is called "network order", while what you're used to is "host order"; same goes for port number. You will find C-based helper functions like htons and ntohs useful in such conversions. These are not syscalls but libc helper functions that swap byte order (endian matters!), so you will find them in section 3, not 2.

And AF_INET6 is for IPv6. Blah.

You will probably be driven mad at first by things like how there's an abstracted interface for interacting with sockets regardless of their type, as well as tons of different syscalls for interacting with sockets (there are a huge number, all varying depending on what you want to do), but also how they all sort of vary in what structure and data you set up in advance. You're literally throwing yourself into literally 50 years of tech evolution (number is not a joke).

Look up some tutorials online (you will find many; this one I skimmed seems pretty good for starters) or rent/buy/borrow from a library some books on UNIX socket programming. And anyone who tells you "sockets are easy!" is lying to you; do not listen to these people. There is an extremely close relationship between socket-related functions (as well as read/write for I/O) and underlying TCP stack behaviour, and you will run into this eventually no matter what PL you use (higher level PLs hide it from you and often make solving real problems difficult). Error handling is equally important.

Likewise, X can run on many, and you also didn't specify what X you're using; for all I know you could be playing with Accelerated-X or classic XFree86 rather than X.org. Worse, X uses terms very strangely; "client" and "server" do not tend to mean what they mean in most other common-day contexts. Prepare to get confused easily. And none of this even begins to touch on the X protocol itself.

I've usually only seen X interfaced with via localhost/loopback (ex. 127.0.0.1) or over a local network via TCP (which is how things like export DISPLAY=1.2.3.4:0.0 work via TCP port 6000; details of that syntax). If X supports UNIX domain sockets then great, give it a try, but I've only seen it historically used via TCP.

Drew Sebastino wrote:
I get the feeling no one really does this stuff without using libraries... It's become apparent to me that there's really not much at all to be gained by using assembly over C here either; half of what I've been doing is just moving immediate values into registers, which a compiler will do just as well. Of course, that holds true for most programming now a days. :lol:

If by "libraries" you mean C, or "other PLs with frameworks that eventually trickle down into C and/or related bits", then correct. What I underlined of yours is a good conclusion though; I just hope you re-read your own words and let them sink in. Your time is more valuable than this, I assure you. Use C and some related Qt framework, or even some general X.org interface library, and you will be happier.


Last edited by koitsu on Tue Jul 09, 2019 1:32 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 1:23 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 970
The sockaddr structure should consist of family, port, ip-address, padding bytes. There should be no filename string in there.
The connect function should be well described in windows api or similar documents, including the format of the corresponding structures.

Calling that functions in asm shouldn't be more complicated as in high level languages, except that you need to figure out how to pass the parameters, which you seem to know already. Passing them in rdx, rsi, rdi is a bit different from win32 (there you would instead push them on stack before calling the function).

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 1:28 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 965
Even making a GUI Hello World in asm will take you about 10k lines.


Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 1:41 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 970
Calling GUI functions in asm is also done just the same as calling the same functions in high level languages.

Maybe you will need a few more lines when using a separate opcode for each parameter, but even if the hello world code program should happen to call a handful of functions with several parameters... that can't sum up to 10,000 lines, no way (unless linux is somewhat ways more complicated to use than win32).

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 9:49 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 965
He was against using libraries. So no calling XCreateWindow and friends via asm, but painstakingly creating each network request, and handling responses.


Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 3:16 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 970
Things like socket, connect, ReadFile, WriteFile, CreateWindow, MessageBox, DialogBoxXxx are all part of the OS, using that functions has nothing to do with libraries. For a quick and dirty Hello World, you could go with calling MessageBox, and the source code would be much smaller than a NES hello world.

The network stuff consists of only a dozen of functions or so (socket, connect, listen, recv, recvfrom, send, sendto, etc., plus things like WSAStartup). It's quite simple and minimalistic. It can be painstaking to figure out how to use that functions in which order, but the very same problem exists for non-asm code, too.

I am not sure what Drew Sebastino meant with libraries. Somethink like using "include" for importing third-party ready-for-use source code? Or loading binary DLL's? Include can be a bit lame (if you want to understand what you code is doing). DLL's can be simple to use if you accept that your code won't work if the DLL doesn't exist, but I would avoid relying on DLL's, or make their use optional.

For hardware based 3D rendering one would need to load OpenGL or DirectX DLL's, and that is actually quite difficult (if it's done with detecting if the DLL exists and which version it is), in that case you might actually end up with 10K lines (asm or not) for a polygon-based hello world.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Tue Jul 09, 2019 5:07 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4199
Talk about "ReadFile, WriteFile, CreateWindow, MessageBox, DialogBoxXxx" and loading "DLLs" is all Windows stuff, and seems a little out of place in Linux land.

In Linux land, you use well defined system calls according to the posix standard. (I think I'm wrong here)

Meanwhile in Windows land, system calls exist too, but they get renumbered with every different version of Windows, so nothing uses the true numbered system calls except for NTDLL.DLL. Kernel32.dll? Just another wrapper for NTDLL.DLL.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Wed Jul 10, 2019 12:31 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 965
Yes, like Dwedit says, you're talking Windows. Incidentally part why it's so unstable and crappy is because the GUI is in kernel.


Top
 Profile  
 
PostPosted: Wed Jul 10, 2019 4:16 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 970
Oh, okay, I guess I have missed the point. I was thinking about asm & network & os calls & GUI functions as separate issues (and especially missed the part about network being needed to access GUI functions).

If I got it right now: Linux kernel doesn't have a GUI at all, and one cannot access the GUI via "call" opcodes or the like.
Instead, one must access the GUI via network send/sendto functions?
That is unfamilar from a dos/windows point of view. And more so from a nes/snes point of view ; )

Makes me wonder if anybody has ever implemented a compact GUI Hello World program for Linux (asm or not)?
Would be interesting if there's a source code package with bare minimum stuff for Hello World.
If it takes 10K lines in asm, then it would probably also take 5K-20K lines in C, right?

If I should ever learn linux coding, I would want to things: Using my own source code (without including third party code), and, especially using 100% asm code (without including third party C code).
Else it wouldn't be fun to say that I had written the program in asm (but didn't have written most of it myself, because it does mainly consist of C written by other people).

Oh, and since I brought up ReadFile/WriteFile: Does linux kernel support any similar functions, or does one also need network sockets for accessing files?

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Wed Jul 10, 2019 4:34 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21558
Location: NE Indiana, USA (NTSC)
Linux provides local file system access. As an option, you can read and write files through FTP, SSH, NFS, or SMB,[1] though in practical programs written in C or C++, network file access is done through user-mode file systems or through "virtual file system" layers provided by desktop environments, such as gvfs.

But the way that used to work on UNIX is that you'd have one computer on which the applications run and a second device that performs input and output, called a terminal. The early terminals were text-based, such as the VT100. Later X terminals supported graphics, and this sort of terminal is what your program sees when displaying GUI elements and receiving input events.


[1] SMB here is a Windows file protocol, not anything involving monkeys or mushrooms. For that matter, NFS doesn't involve illicit auto racing.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Wed Jul 10, 2019 2:28 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4199
Example code:
Code:
FILE *file = fopen(filename);
fread(data, size, count file);
fclose(file);


In Windows, you have this:
Standard C Library Function => Win32 API function (Kernel32.dll, etc) => NTDLL.dll => System call to Kernel
`fopen` calls `CreateFile`, `fread` calls `ReadFile`, `fclose` calls `CloseHandle`.
`CreateFile` calls `NtCreateFile`, `ReadFile` calls `NtReadFile`, `CloseHandle` calls `NtClose`.

In Linux you have this:
Standard C Library function => Posix API function => Linux system call
`fopen` calls `open`, `fread` calls `read`, `fclose` calls `close`.
`open` is implemented by system call 05 `sys_open`, `read` is implemented by system call 03 `sys_read`, and `close` is implemented by system call 06 `sys_close`.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Fri Jul 12, 2019 1:10 pm 
Offline

Joined: Sun Sep 19, 2004 11:07 pm
Posts: 172
File IO and stdlib stuff has been covered already

nocash wrote:
Oh, okay, I guess I have missed the point. I was thinking about asm & network & os calls & GUI functions as separate issues (and especially missed the part about network being needed to access GUI functions).

If I got it right now: Linux kernel doesn't have a GUI at all, and one cannot access the GUI via "call" opcodes or the like.
Instead, one must access the GUI via network send/sendto functions?
That is unfamilar from a dos/windows point of view. And more so from a nes/snes point of view ; )

Sort of. There are similar splits between the kernel, window manager, widgets, and rendering interface on windows, but it isn't quite as obvious as the programming interfaces across them are a bit more consistent, and there aren't generally a wide variety of options. A rough breakdown of what most windows programs link to, and the closest analog for linux:

  • kernel32.dll -- Basic system services, file IO, etc. Provides the core of the Win32 API to programs, via syscalls down to NTDLL

    Linux equivalent is glibc (providing the wrappers to do the actual system calls), which poke the kernel to do the work

  • user32.dll -- Window management, gui message handling, user interface widgets, IO glue. Provides the basic win32 window and control classes.

    Linux equivalent is a combination of the X display server, destop environment/window manager, and widget libraries like Xt, Xaw, gtk, and Motif. Programs communicate with the X server via a socket, which could be a real network socket, or a local pipe. Generally people link against Xlib, which provides a C language interface for managing that connection and exposing the message types. Widget libraries are a layer in between, that provide various widgets and controls, in a particular style.

  • gdi32.dll -- GUI rendering and painting

    Linux deals with this inside the X display server, mostly via requests similar to a WM_PAINT message.

  • comdlg32.dll/comctl32.dll -- Fancier looking widgets and common dialogs. Where most of the 3D-look bits of the windows UI come from.

    Linux equivalent would be the widget libraries, where the code is providing the equivalent of the new message types and the window procedure

  • shell32.dll

    Explorer and window manager interface


On a linux system, running X or a compatible display server (the usual approach to guis that play nicely with others), programs communicate with an X display server. This is another process, that usually encompasses the display drivers, and provides controlled access to the screen and user interface devices via a well defined protocol suitable for use over a network. There are a bunch of extensions to make this process more efficient when running locally. It only provides basic window tests and messaging -- all painting and interface policy is up to the programs themselves.

There is another process usually running, the Window Manager, which provides the actual desktop interface. In windows, this would be what handles most of the non-client area. Programs communicate with it via X messages, sent through the display server. It generally provides title bars, close buttons, task bars, etc. A lot of them these days come as part of a larger desktop environment, packaging the window manager up with a number of expected utilities, like file managers, calculators, and such.

In windows, when you create your toplevel window, it distinguishes between the client area and non-client area, depending on your window style, and the system provides various bits in the non-client area. On Linux, when you create a toplevel window, the window manager gets a message about it, and it creates its own windows to provide those features. Message routing is slightly different, on X you would generally only see messages for your client window, on Windows, you would see messages related to the non-client area, but DefWndProc takes care of passing them on for you.

nocash wrote:
Makes me wonder if anybody has ever implemented a compact GUI Hello World program for Linux (asm or not)?
Would be interesting if there's a source code package with bare minimum stuff for Hello World.
If it takes 10K lines in asm, then it would probably also take 5K-20K lines in C, right?

The usual thing here would be Xlib only, or Xlib+Xt only minimalist programs. The C versions would probably be smaller in terms of code, given the conciseness of passing arguments around. Talking to the X server via raw Xlib calls is a bit lower level than raw Win32 without MFC, and punts a lot more on to you. Xlib+Xt is the closest equivalent to that, providing basic widgets like menu bars, scroll bars, and buttons.

nocash wrote:
If I should ever learn linux coding, I would want to things: Using my own source code (without including third party code), and, especially using 100% asm code (without including third party C code).
Else it wouldn't be fun to say that I had written the program in asm (but didn't have written most of it myself, because it does mainly consist of C written by other people).

This depends on exactly what you mean by third party code, and where you draw the line. You could talk directly to NTDLL on windows, and bypass CreateFile and friends, but I doubt you go down that route.

If you're aiming at the linux equivalent of dealing with raw Win32, including the standard controls (static text, buttons, menus, scrollbars, maybe the common file dialog), that would be writing against a subset of glibc (for system calls), Xlib (for the PeekMessage, CreateWindow equivalents), and Xt (for the basic widgets)

If you're aiming even lower than that, and issuing the syscalls directly from assembly, that will of course differ between x86, arm, ppc and amd64. You could speak directly to the server via socket related syscalls, but you will basically be reimplementing Xlib. It does not do that much in the way of fancy buffer management or anything.


Top
 Profile  
 
PostPosted: Fri Jul 12, 2019 4:06 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21558
Location: NE Indiana, USA (NTSC)
ReaperSMS wrote:
kernel32.dll -- Basic system services, file IO, etc. Provides the core of the Win32 API to programs, via syscalls down to NTDLL

Linux equivalent is glibc (providing the wrappers to do the actual system calls), which poke the kernel to do the work

Does Linux have an equivalent to the divide between kernel32 and msvcrt?

ReaperSMS wrote:
Talking to the X server via raw Xlib calls is a bit lower level than raw Win32 without MFC, and punts a lot more on to you. Xlib+Xt is the closest equivalent to that, providing basic widgets like menu bars, scroll bars, and buttons.

And Xt is X Toolkit Intrinsics.

ReaperSMS wrote:
You could speak directly to the server via socket related syscalls, but you will basically be reimplementing Xlib.

And that'd just make you Bart Massey, who developed XCB, a lower-level alternative to Xlib.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Fri Jul 12, 2019 4:44 pm 
Offline

Joined: Sun Sep 19, 2004 11:07 pm
Posts: 172
tepples wrote:
Does Linux have an equivalent to the divide between kernel32 and msvcrt?

That divide sort of exists in glibc, in that the kernel32 type bits would be in unistd.h, and various sys/*.h files, with the usual libc bits in stdio and friends. It usually exposes a direct syscall() macro/inline function for more direct work. It does exist at the system level, in that the real work of the kernel32 bits are handled in the kernel itself on the other side of the syscall() machinery. The linux NTDLL equivalent would be the low level guts of the kernel, subject to change at a whim, with few if any promises about forward compatability. The syscall interface is meant to stay stable as much as possible, as breaking that means application binaries quit working. Making a userland-visible change to those is a great way to end up on the wrong end of a Linus flame.

If you're trying to avoid glibc entirely, it is indeed possible, but not very practical. The kernel doesn't really care what's in the elf, it just does what the elf header says to do -- but one of the entries in there is which dynamic linker it uses, which is part of the glibc package (though it lives around /bin/ld.so IIRC). It will have its own expectations, and the documentation for those may leave much to the imagination.

You could write a program to go from the bare metal 'start' entry point, but you would not have much luck linking to anything else, as many of them will expect the C runtime to have been initialized and available. It's been a while since I dug through that approach.
tepples wrote:
ReaperSMS wrote:
You could speak directly to the server via socket related syscalls, but you will basically be reimplementing Xlib.

And that'd just make you Bart Massey, who developed XCB, a lower-level alternative to Xlib.

Ah yeah, I remember reading about that semi-recently. It would likely serve as a decent alternative to talking directly to Xlib, for a minimal approach.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group