flat assembler
Message board for the users of flat assembler.

Index > Linux > Thanks to all

Goto page Previous  1, 2, 3  Next
Author
Thread Post new topic Reply to topic
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 27 Jun 2022, 17:03
Thanks @revolution for the detailed explanation.
Post 27 Jun 2022, 17:03
View user's profile Send private message Reply with quote
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 27 Jun 2022, 17:06
There are no differences between hello.asm and hello.cpp in term of coding, so why hello.cpp can show "Hello World" while hello.asm is still "empty window"?

HELLO.CPP
Code:
//g++ -Wall -g -std=c++11 hello.cpp -L/usr/lib/X11 -lX11 -o hello

#include <X11/Xlib.h>
#include <string.h>

int main(int, char**)
{
    Display *d = XOpenDisplay(0);
    Window r = DefaultRootWindow(d);
    Window w = XCreateSimpleWindow(d, r, 0, 0, 256, 256, 0, 0, 0xffffff);
    GC gc = DefaultGC(d, 0);

    XMapRaised(d, w);
    XSelectInput(d, w, ExposureMask);

    Font font = XLoadFont(d, "fixed");
    XSetFont(d, gc, font);

    const char *msg = "Hello World"; // cyrillic symbols

    while (1)
    {
        XEvent e;
        XNextEvent(d, &e);
        XDrawString(d, w, gc, 16, 16, msg, (int) strlen(msg));
    }
}
    


HELLO.ASM
Code:
format ELF64 executable 3

SYMBOL_TABLE_ENTRY64.size = $18
RELOC_TABLE_ENTRY64.size = $18
StrTabEntry equ -STRING_TABLE+
R_X86_64_JUMP_SLOT = 7

DT_NULL         = 0
DT_NEEDED       = 1
DT_HASH         = 4
DT_STRTAB       = 5
DT_SYMTAB       = 6
DT_RELA         = 7
DT_RELASZ       = 8
DT_RELENT       = 9
DT_STRSZ        = 10
DT_SYMENT       = 11

win_width       =       256
win_height      =       256
sys_exit        =       $3C
msg_x        = 16
msg_y        = 16

segment interpreter readable
        db '/lib64/ld-linux-x86-64.so.2',0

segment dynamic readable
DYNAMIC_TABLE:
        dq DT_NEEDED,StrTabEntry(str@libX11.so.6)
        dq DT_STRTAB,STRING_TABLE
        dq DT_SYMTAB,SYMBOL_TABLE
        dq DT_RELA,RELOC_TABLE
        dq DT_RELASZ,relasz
        dq DT_RELENT,RELOC_TABLE_ENTRY64.size
        dq DT_STRSZ,strsz
        dq DT_SYMENT,SYMBOL_TABLE_ENTRY64.size
        dq DT_NULL,0

SYMBOL_TABLE:
        dd 0,0,0,0,0,0
        dd StrTabEntry(str@XMapRaised),$12,0,0,0,0
        dd StrTabEntry(str@XCreateSimpleWindow),$12,0,0,0,0
        dd StrTabEntry(str@XNextEvent),$12,0,0,0,0
        dd StrTabEntry(str@XSelectInput),$12,0,0,0,0
        dd StrTabEntry(str@XOpenDisplay),$12,0,0,0,0
        dd StrTabEntry(str@XCreateGC),$12,0,0,0,0
        dd StrTabEntry(str@XDrawString),$12,0,0,0,0
        dd StrTabEntry(str@XSetFont),$12,0,0,0,0
        dd StrTabEntry(str@XLoadFont),$12,0,0,0,0
        dd StrTabEntry(str@XDefaultRootWindow),$12,0,0,0,0
        dd StrTabEntry(str@XDefaultGC),$12,0,0,0,0 

STRING_TABLE:                   db 0
str@libX11.so.6                 db 'libX11.so.6',0
str@XMapRaised                  db 'XMapRaised',0
str@XCreateSimpleWindow         db 'XCreateSimpleWindow',0
str@XNextEvent                  db 'XNextEvent',0
str@XSelectInput                db 'XSelectInput',0
str@XOpenDisplay                db 'XOpenDisplay',0
str@XCreateGC                   db 'XCreateGC',0
str@XDrawString                 db 'XDrawString',0
str@XSetFont                    db 'XSetFont',0
str@XLoadFont                   db 'XLoadFont',0
str@XDefaultRootWindow          db 'XDefaultRootWindow',0
str@XDefaultGC                  db 'XDefaultGC',0
strsz = $-STRING_TABLE

align $8

RELOC_TABLE:
        dq XMapRaised,          R_X86_64_JUMP_SLOT+ 1 shl 32, 0
        dq XCreateSimpleWindow, R_X86_64_JUMP_SLOT+ 2 shl 32, 0
        dq XNextEvent,          R_X86_64_JUMP_SLOT+ 3 shl 32, 0
        dq XSelectInput,        R_X86_64_JUMP_SLOT+ 4 shl 32, 0
        dq XOpenDisplay,        R_X86_64_JUMP_SLOT+ 5 shl 32, 0
        dq XCreateGC,           R_X86_64_JUMP_SLOT+ 6 shl 32, 0
        dq XDrawString,         R_X86_64_JUMP_SLOT+ 7 shl 32, 0
        dq XSetFont,            R_X86_64_JUMP_SLOT+ 8 shl 32, 0
        dq XLoadFont,           R_X86_64_JUMP_SLOT+ 9 shl 32, 0
        dq XDefaultRootWindow,  R_X86_64_JUMP_SLOT+ 10 shl 32, 0
        dq XDefaultGC,          R_X86_64_JUMP_SLOT+ 11 shl 32, 0
        relasz = $-RELOC_TABLE

segment readable writeable executable

entry $
        ;Display *XOpenDisplay(char *display_name);
        xor     edi,edi
        call    [XOpenDisplay]
        mov     qword [disp],rax
        
        ;Window XDefaultRootWindow(Display *display);
        mov     rdi, qword [disp]
        call    [XDefaultRootWindow]
        mov     qword [root], rax
        
        ;Window XCreateSimpleWindow(Display *display, Window parent, intx, y, unsignedintwidth, height, unsignedint border_width, unsignedlong border, unsignedlong background);
        
        push    0xFFFFFF
        push    0
        push    0
        mov     r9, win_height
        mov     r8, win_width
        xor     rcx, rcx
        xor     rdx, rdx
        mov     rsi, qword [root]
        mov     rdi, qword [disp]
        call    [XCreateSimpleWindow]
        mov     qword [win],rax
        
        ;XMapRaised(Display *display, Window w);
        mov     rsi,qword [win]
        mov     rdi,qword [disp]
        call    [XMapRaised]
        
        ;XSelectInput(Display *display, Window w, long event_mask);
        xor     edx,edx
        mov     rsi, qword [win]
        mov     rdi,qword [disp]
        call    [XSelectInput] 
        
        ;GC XDefaultGC(Display *display, int screen_number);
        xor     rsi, rsi
        mov     rdi, qword [disp]
        call    [XDefaultGC]
        mov     qword [gc], rax 
        
        ;Font XLoadFont(Display *display, char *name);
        lea     rsi, [font_name]
        mov     rdi, qword [disp]
        call    [XLoadFont] 
        mov     qword [font_id], rax
        
        ;XSetFont(Display *display, GC gc, Font font);
        mov     rdx, qword [font_id]
        mov     rsi, qword [gc]
        mov     rdi, qword [disp]
        call    [XSetFont] 
        
        ;XDrawString(Display *display, Drawable d, GC gc, int x, int y, char *string, int length);        
        push    len
        lea     r9, [msg]
        mov     r8, msg_y        
        mov     rcx, msg_x
        mov     rdx, qword [gc]
        mov     rsi,qword [win]  ;drawable
        mov     rdi,qword [disp]
        call    [XDrawString] 
 
event_loop:
        lea     rsi,[event]
        mov     rdi,qword [disp]
        call    [XNextEvent]
        jmp     event_loop

;        mov     rsi,qword [gc]
;        mov     rdi,qword [disp]
;        call    [XFreeGC]

;        mov     rdi,qword [disp]
;        call    [XCloseDisplay]

segment readable writeable
disp            dq ?
root            dq ?
win             dq ?
gc              dq ?,?
msg             db "Hello World!",0
len             = $ - msg
;font_name      db "fixed",0  
font_name       db "*helvetica-bold-r-normal--18*",0
font_id         dq ?

event           rb $C0
align 8
virtual
        XMapRaised              dq ?
        XCreateSimpleWindow     dq ?
        XNextEvent              dq ?
        XSelectInput            dq ?
        XOpenDisplay            dq ?
        XCreateGC               dq ?
        XDrawString             dq ?
        XSetFont                dq ?
        XLoadFont               dq ?
        XDefaultRootWindow      dq ?
        XDefaultGC              dq ?
end virtual    

    


Description: Output of hello.asm
Filesize: 13.01 KB
Viewed: 9341 Time(s)

helloasm.png


Description: Output of hello.cpp
Filesize: 17.56 KB
Viewed: 9342 Time(s)

hellocpp.png


Post 27 Jun 2022, 17:06
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 27 Jun 2022, 19:02
I expect that your ExposureMask is not correct.

Try a value like 2 instead of 0.

Edit: X.h defines ExposureMask = 0x8000
Code:
#define NoEventMask                     0L
#define KeyPressMask                    (1L<<0)  
#define KeyReleaseMask                  (1L<<1)  
#define ButtonPressMask                 (1L<<2)  
#define ButtonReleaseMask               (1L<<3)  
#define EnterWindowMask                 (1L<<4)  
#define LeaveWindowMask                 (1L<<5)  
#define PointerMotionMask               (1L<<6)  
#define PointerMotionHintMask           (1L<<7)  
#define Button1MotionMask               (1L<<8)  
#define Button2MotionMask               (1L<<9)  
#define Button3MotionMask               (1L<<10) 
#define Button4MotionMask               (1L<<11) 
#define Button5MotionMask               (1L<<12) 
#define ButtonMotionMask                (1L<<13) 
#define KeymapStateMask                 (1L<<14)
#define ExposureMask                    (1L<<15) 
#define VisibilityChangeMask            (1L<<16) 
#define StructureNotifyMask             (1L<<17) 
#define ResizeRedirectMask              (1L<<18) 
#define SubstructureNotifyMask          (1L<<19) 
#define SubstructureRedirectMask        (1L<<20) 
#define FocusChangeMask                 (1L<<21) 
#define PropertyChangeMask              (1L<<22) 
#define ColormapChangeMask              (1L<<23) 
#define OwnerGrabButtonMask             (1L<<24)     
Post 27 Jun 2022, 19:02
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 27 Jun 2022, 19:33
Note that your code never restores the stack. It just keeps pushing more values!

Eventually your could run out of stack and it will crash.

For the simple loop above I guess it will be fine, but once you make it more complex and have other stuff, then problems can begin to appear.
Post 27 Jun 2022, 19:33
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4075
Location: vpcmpistri
bitRAKE 28 Jun 2022, 02:00
FlierMate1 wrote:
why hello.cpp can show "Hello World" while hello.asm is still "empty window"?
The C++ code is clearly calling XDrawString within the WHILE loop.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 28 Jun 2022, 02:00
View user's profile Send private message Visit poster's website Reply with quote
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 28 Jun 2022, 06:12
revolution wrote:
I expect that your ExposureMask is not correct.
Try a value like 2 instead of 0.


I tried to set EDX to 2, but it is still the same.

revolution wrote:
Note that your code never restores the stack. It just keeps pushing more values!


I am not good in anything related to stack handling, perhaps someone can show me how. Embarassed

bitRAKE wrote:
The C++ code is clearly calling XDrawString within the WHILE loop.


Nice catch. I tried placing XDrawString in the WHILE loop, but it is still the same, empty window.
Post 28 Jun 2022, 06:12
View user's profile Send private message Reply with quote
I



Joined: 19 May 2022
Posts: 58
I 28 Jun 2022, 07:36
Missing ExposureMask in XSelectInput.
mov edx, 1 shl 15
Post 28 Jun 2022, 07:36
View user's profile Send private message Reply with quote
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 28 Jun 2022, 08:56
I wrote:
Missing ExposureMask in XSelectInput.
mov edx, 1 shl 15


Brilliant, man!

revolution wrote:

I expect that your ExposureMask is not correct.


It was @revolution who found it first, but @I suggested a correct value.


Description: Yeah!
Filesize: 17.92 KB
Viewed: 9283 Time(s)

helloasm2.png


Post 28 Jun 2022, 08:56
View user's profile Send private message Reply with quote
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 28 Jun 2022, 09:08
I am attaching the source modified from ProMiNick's example to display processor name in a GUI window.

Yes, the XDrawString must be in WHILE loop, thanks @bitRAKE for that.


Description: Example application of GUI window
Filesize: 18.89 KB
Viewed: 9283 Time(s)

guicpuid.png


Description: Source of working GUI window with XDrawString
Download
Filename: guicpuid.asm
Filesize: 6.61 KB
Downloaded: 350 Time(s)

Post 28 Jun 2022, 09:08
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 28 Jun 2022, 12:39
FlierMate1 wrote:
It was @revolution who found it first, but @I suggested a correct value.
Haha, okay. I guess you didn't read, or didn't understand, the edit I made.
Code:
#define ExposureMask                    (1L<<15)    
Post 28 Jun 2022, 12:39
View user's profile Send private message Visit poster's website Reply with quote
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 28 Jun 2022, 12:44
revolution wrote:
FlierMate1 wrote:
It was @revolution who found it first, but @I suggested a correct value.
Haha, okay. I guess you didn't read, or didn't understand, the edit I made.
Code:
#define ExposureMask                    (1L<<15)    


I could have solved it earlier if I didn't overlook your "ExposureMask = 0x8000". Sorry, after I reread it I fully understand.
Post 28 Jun 2022, 12:44
View user's profile Send private message Reply with quote
I



Joined: 19 May 2022
Posts: 58
I 29 Jun 2022, 02:17
Cool, thanks for the code. I wouldn't have known where to start, now I do. Smile

I cheated a bit and used cutter on the compiled C++, see below. Hope I have commented correctly (green). Cutter is work in progress but have found it handy for Linux and even learnt a little about Linux Arm ASM too. Runs on Win, Linux, Mach although I haven't tried the Mach version.

The strings don't need zero termination, just the length of the text. That's why those dashed boxes appear at the end.

Interestingly the g++ compiler didn't call a couple of functions but parsed the structures instead. Like XDefaultGC instead gets gc from the screen structure which is pointed to from the disp structure. Something like
Code:
 mov rax,[disp.Screen]
 mov rax [rax+default_gc]
 mov [gc], rax    


Description: Some Cutter output
Filesize: 65.47 KB
Viewed: 9212 Time(s)

cutter.png


Post 29 Jun 2022, 02:17
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4075
Location: vpcmpistri
bitRAKE 29 Jun 2022, 03:03
The disassembly also makes clear the stack alignment and correction needed for XDrawString, within the event loop. I've not read the related documentation/code, but I'm assuming the calling convention.

The C code here also shows event loop exit and program termination - which is probably a good idea.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 29 Jun 2022, 03:03
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 29 Jun 2022, 03:48
bitRAKE wrote:
The disassembly also makes clear the stack alignment and correction needed for XDrawString, within the event loop. I've not read the related documentation/code, but I'm assuming the calling convention.
Linux has no alignment requirements. Perhaps the posted code is for WSL? But even that doesn't make sense to me.
Post 29 Jun 2022, 03:48
View user's profile Send private message Visit poster's website Reply with quote
I



Joined: 19 May 2022
Posts: 58
I 29 Jun 2022, 04:55
@bitRAKE thanks for the link.

Yes, I was wondering about the alignment, seems to push for 16byte alignment (forgive the pun) as seen with the question marked sub rsp,8 before a single push. Does seem to work without it IIRC. Also a bit puzzled by the zealous use of rcx and rax by g++.

Checking Agner Fog's article on Alignment chapter 5 it states
Quote:
The 64 bit systems keep the stack aligned by 16. The stack word size is 8 bytes, but the stack must be aligned by 16 before any call instruction. Consequently, the value of the stack pointer is always 8 modulo 16 at the entry of a procedure. A procedure must subtract an odd multiple of 8 from the stack pointer before any call instruction. A procedure can rely on these rules when storing XMM data that require 16-byte alignment. This applies to all 64 bit systems (Windows, Linux, BSD).

Or maybe I've misunderstood it?
Post 29 Jun 2022, 04:55
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4075
Location: vpcmpistri
bitRAKE 29 Jun 2022, 05:24
I was wrong about correct window termination - an explicit message needs to be relayed to exit without error:
Code:
#include <X11/Xlib.h>
#include <string.h>

int main(int, char**) {
    Display *display = XOpenDisplay(0);
    GC gc = DefaultGC(display, 0);
    Font font = XLoadFont(display, "fixed");
    XSetFont(display, gc, font);

    Window root = DefaultRootWindow(display);
    Window window = XCreateSimpleWindow(
        display, root, 0, 0, 256, 256, 0, 0, 0xffffff);

    Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(display, window, &wmDeleteMessage, 1);

    XSelectInput(display, window, ExposureMask | StructureNotifyMask);
    XMapRaised(display, window);
    while (1) {
        XEvent event;
        XNextEvent(display, &event);
        if (event.type == Expose) {
            const char *msg = "Hello World";
            XDrawString(display, window, gc,
                16, 16, msg, (int) strlen(msg));
        } else if (event.type == ClientMessage) {
            if (event.xclient.data.l[0] == wmDeleteMessage) {
                XDestroyWindow(display, window);
                XCloseDisplay(display);
                break;
            }

        }
    }
    return 0;
}    
The alignment is quite explicit in all the binaries I looked at. I just wish the compiler would push a random register instead of all the SUB RSP,8 nonsense. If I compile with "-Oz" it will clear up some of the stack pointer motion, but not all. If I compile for speed, the stack is adjusted outside the loop - well done, compiler.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 29 Jun 2022, 05:31; edited 1 time in total
Post 29 Jun 2022, 05:24
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 29 Jun 2022, 05:30
I wrote:
Checking Agner Fog's article on Alignment chapter 5 it states
Quote:
The 64 bit systems keep the stack aligned by 16. The stack word size is 8 bytes, but the stack must be aligned by 16 before any call instruction. Consequently, the value of the stack pointer is always 8 modulo 16 at the entry of a procedure. A procedure must subtract an odd multiple of 8 from the stack pointer before any call instruction. A procedure can rely on these rules when storing XMM data that require 16-byte alignment. This applies to all 64 bit systems (Windows, Linux, BSD).

Or maybe I've misunderstood it?
I expect that is only for movdqa. There is no requirement for anything else to be aligned. Not even RSP, you can make RSP anything and Linux doesn't care.

Perhaps the alignment is for "speed"?
Post 29 Jun 2022, 05:30
View user's profile Send private message Visit poster's website Reply with quote
I



Joined: 19 May 2022
Posts: 58
I 29 Jun 2022, 07:52
@revolution maybe that's it then, how can we guarantee that instruction isn't in a library function, now or sometime in the future.

https://board.flatassembler.net/topic.php?t=22256&start=14

Your smaller second clod64 1k code for me on Fedora x64 34 and 36

[alex@fedora bw]$ ./clod64
Segmentation fault (core dumped)

The first clod64 code you posted worked fine, nice work BTW. If I change the stack alignment as so
Code:
start:
        sub     rsp,0x8
        invoke  SDL_Init,SDL_INIT_VIDEO
        test    rax,rax
        mov     ebp,1
        jnz     .err
        mov     rbx,SDL_OPENGL
        cmp     qword[rsp],1                            ;full screen?
        jbe     .set_mode
;        mov     rbx,SDL_OPENGL or SDL_FULLSCREEN
;        invoke  SDL_ShowCursor,0
    .set_mode:
        invoke  SDL_SetVideoMode,x_res,y_res,0,rbx    
it causes "Segmentation fault (core dumped)" and for every hex number ending in 8 that I tried while ending in 0 worked well. Of course I haven't tried every number, maybe 5 or 6 of each. The commented code is because subtracting 0x20 and up from rsp gives full screen otherwise.
Post 29 Jun 2022, 07:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 29 Jun 2022, 08:47
You changed rbx, so the call to SDL_SetVideoMode is not correct. The change you made doesn't affect the stack, all the parameters are passed in registers.
Post 29 Jun 2022, 08:47
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20454
Location: In your JS exploiting you and your system
revolution 29 Jun 2022, 08:49
I wrote:
@revolution maybe that's it then, how can we guarantee that instruction isn't in a library function, now or sometime in the future.
It isn't part of the Linux spec, so it will be fine. Really, it will be fine. Don't worry about it.

I had another thread discussing the Windows RSP, and many there seem unconvinced also. A lot of superstition over RSP usage. Razz
Post 29 Jun 2022, 08:49
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3  Next

< Last Thread | Next Thread >
Forum Rules:
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 vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.