flat assembler
Message board for the users of flat assembler.
Index
> Linux > Porting 16-bit .com assembly to 64-bit Linux counterpart Goto page 1, 2 Next |
Author |
|
YONG 08 Jul 2017, 07:28
I would like to port my .com game written 12 years ago to 64-bit Linux, which, I believe, is a good exercise to brush up my rusty assembly programming skills.
I quickly encountered a problem -- the code related to the 80x25 TEXT video mode could not be directly converted. After some digging, I found the following links: Fastest and very "assembly" way to draw in Linux https://board.flatassembler.net/topic.php?t=17752 very simple example creating a window/displaying graphics https://board.flatassembler.net/topic.php?t=13567 Frankly, doing graphics on X Window or Linux seems to be quite troublesome. So, my question is: What is the simplest/easiest way to do 80x25 TEXT on X Window or Linux? I don't need any fancy graphics. Thanks in advance! Preemptive strike: @Furs: No need to suggest using a sandbox or emulator. 64-bit Linux is my workhorse OS; I would like to run my program natively. @revolution: Nope. Your fake website does not contain any useful information. Do NOT confuse clickbaits with jokes. |
|||
08 Jul 2017, 07:28 |
|
redsock 08 Jul 2017, 22:04
I'm not sure whether my library's TUI goods are "simple" exactly, but I coded up a short and sweet "demo" of drawing/moving an X with cursor keys across a background in text mode/terminal window
Code: include '../../ht_defaults.inc' include '../../ht.inc' globals { x dd 0 y dd 0 } falign our_draw: prolog our_draw push rdi call tui_background$nvfill pop rdi cmp dword [rdi+tui_width_ofs], 0 je .nothingtodo cmp dword [rdi+tui_height_ofs], 0 je .nothingtodo mov eax, [rdi+tui_width_ofs] mov r8, [rdi+tui_text_ofs] mov r9, [rdi+tui_attr_ofs] mov ecx, [y] mul ecx add eax, [x] shl eax, 2 ansi_colors r10d, 'red', 'blue' mov dword [r8+rax], 'X' mov dword [r9+rax], r10d .nothingtodo: mov rsi, [rdi] ; load the vtable call qword [rsi+tui_vupdatedisplaylist] epilog ; three arguments: rdi == our tui_background, esi == key, edx == esc_key ; NOTE: return zero in eax if firekeyevent should keep walking up "bubbling" ; and return nonzero in eax if firekeyevent should STOP falign our_keyevent: prolog our_keyevent ; check for cursor keys mov r8d, [rdi+tui_width_ofs] mov r9d, [rdi+tui_height_ofs] cmp edx, 0x41 ; up arrow je .uparrow cmp edx, 0x42 ; down arrow je .downarrow cmp edx, 0x43 ; right arrow je .rightarrow cmp edx, 0x46 ; end, well, shift-end je .shiftend cmp edx, 0x44 ; left arrow je .leftarrow .bailout: xor eax, eax epilog .uparrow: cmp [y], 0 je .bailout sub [y], 1 jmp .redraw .downarrow: cmp [y], r9d jae .bailout add [y], 1 jmp .redraw .rightarrow: cmp [x], r8d jae .bailout add [x], 1 jmp .redraw .shiftend: mov [x], r8d sub [x], 1 jmp .redraw .leftarrow: cmp [x], 0 je .bailout sub [x], 1 .redraw: call our_draw mov eax, 1 epilog ; a modified copy of tui_background$vtable so we can catch input and customise ; the draw method: dalign our_vtable: dq tui_object$cleanup, tui_background$clone, our_draw, tui_object$redraw, tui_object$updatedisplaylist, tui_object$sizechanged dq tui_object$timer, tui_object$layoutchanged, tui_object$move, tui_object$setfocus, tui_object$gotfocus, tui_object$lostfocus dq our_keyevent, tui_object$domodal, tui_object$endmodal, tui_object$exit, tui_object$calcbounds, tui_object$calcchildbounds dq tui_object$appendchild, tui_object$appendbastard, tui_object$prependchild, tui_object$contains, tui_object$getchildindex dq tui_object$removechild, tui_object$removebastard, tui_object$removeallchildren, tui_object$removeallbastards dq tui_object$getobjectsunderpoint, tui_object$flatten, tui_object$firekeyevent, tui_object$ontab, tui_object$onshifttab dq tui_object$setcursor, tui_object$showcursor, tui_object$hidecursor, tui_object$click, tui_object$clicked public _start calign _start: ; initialise HeavyThing... call ht$init ; allocate enough room for our tui_background mov edi, tui_background_size call heap$alloc mov rbx, rax ; save it mov rdx, our_vtable ; use our custom vtable mov [rax], rdx ; save vtable mov rdi, rax ; setup for call to init_dd movq xmm0, [_math_onehundred] ; 100% width movq xmm1, [_math_onehundred] ; 100% height mov esi, '.' ; fillchar ansi_colors edx, 'lightgray', 'blue' ; colours call tui_background$init_dd mov rdi, rbx call tui_terminal$new call epoll$run ; doesn't come back include '../../ht_data.inc' Edit: Suppose I should explain that the library exposes what amounts to two flat 32bit buffers, one for characters and the other for attributes. So the above example just uses the global variables in [x] and [y] to determine where to put the X, and places the red foreground and blue background attributes at the same location/offset into the buffers. When the draw method calls updatedisplaylist, that triggers the library's "differential" ansi output sequences (such that it is not actually drawing the entire "screen" each and every keypress, only the parts of the screen that changed since its last update). Resizing the terminal window works as you'd expect, etc. etc. While I could have fixed the tui_background size to 80x25, having it auto-fill a terminal window is better IMO The other two library pieces I wrote, sshtalk and hnwatch both make heavy use of the tui_* components for further examples. Let me know if you'd like me to explain further |
|||
08 Jul 2017, 22:04 |
|
YONG 09 Jul 2017, 03:29
Just tried and had a compilation error:
flat assembler version 1.71.63 (16384 kilobytes memory, x64) error: out of memory. The error might be caused by some bug in the 64-bit fasm compiler, but I am not sure. Note that the compiler did compile the 64-bit "Hello World" example without any problem. |
|||
09 Jul 2017, 03:29 |
|
redsock 09 Jul 2017, 04:01
YONG wrote: error: out of memory. Code: fasm -m 262144 yoursource.asm && ld -o yoursource yoursource.o |
|||
09 Jul 2017, 04:01 |
|
YONG 09 Jul 2017, 04:31
redsock wrote: try: It seems that the 64-bit fasm compiler has some memory management issue. Anyway. The generated terminal has 80 columns but more than 25 rows (I don't know how many). Besides, navigating the "X" with the arrow keys seems to have some issues. But overall, the generated terminal is what I need. Now, I would have to study the code in detail and see if I can make sense of it. |
|||
09 Jul 2017, 04:31 |
|
redsock 09 Jul 2017, 04:56
YONG wrote: Besides, navigating the "X" with the arrow keys seems to have some issues. |
|||
09 Jul 2017, 04:56 |
|
YONG 09 Jul 2017, 13:01
redsock wrote: let me know how you go. How about ansi_colors? If there is a fully-documented hierarchy of functions/routines (which also shows the dependencies of the .inc files), it will be great! Well, I know that I am asking for too much. |
|||
09 Jul 2017, 13:01 |
|
Tomasz Grysztar 09 Jul 2017, 13:39
YONG wrote: It seems that the 64-bit fasm compiler has some memory management issue. Anyway. |
|||
09 Jul 2017, 13:39 |
|
redsock 09 Jul 2017, 21:47
YONG wrote: Do you maintain a full list of "reserved" names for the HeavyThing library? For example, I suspect that calign, dalign, and falign are some built-in routines for properly aligning code, data, and functions. But that is just my guess. Outside that, the ht_defaults.inc file is the "settings" for the library, and by copying and/or modifying the settings, you can affect how various things are compiled/generated including those alignment macros (which are in align_macros.inc). Since I maintain those alignment standards throughout the library, it is enlightening (IMO) to know whether 16-byte aligned jump targets on a given architecture throughout the entirety of a codebase affect performance, similarly with data, only-function-targets, etc. |
|||
09 Jul 2017, 21:47 |
|
redsock 09 Jul 2017, 21:57
Morning coffee today resulted in a quick modification of the demo (noting I still didn't mess with bounds checking haha), this one randomly moves the X every 100ms
Code: include '../../ht_defaults.inc' include '../../ht.inc' globals { x dd 0 y dd 0 bg dq 0 } falign our_draw: prolog our_draw push rdi call tui_background$nvfill pop rdi cmp dword [rdi+tui_width_ofs], 0 je .nothingtodo cmp dword [rdi+tui_height_ofs], 0 je .nothingtodo mov eax, [rdi+tui_width_ofs] mov r8, [rdi+tui_text_ofs] mov r9, [rdi+tui_attr_ofs] mov ecx, [y] mul ecx add eax, [x] shl eax, 2 ansi_colors r10d, 'red', 'blue' mov dword [r8+rax], 'X' mov dword [r9+rax], r10d .nothingtodo: mov rsi, [rdi] ; load the vtable call qword [rsi+tui_vupdatedisplaylist] epilog ; three arguments: rdi == our tui_background, esi == key, edx == esc_key ; NOTE: return zero in eax if firekeyevent should keep walking up "bubbling" ; and return nonzero in eax if firekeyevent should STOP falign our_keyevent: prolog our_keyevent ; check for cursor keys mov r8d, [rdi+tui_width_ofs] mov r9d, [rdi+tui_height_ofs] cmp edx, 0x41 ; up arrow je .uparrow cmp edx, 0x42 ; down arrow je .downarrow cmp edx, 0x43 ; right arrow je .rightarrow cmp edx, 0x46 ; end, well, shift-end je .shiftend cmp edx, 0x44 ; left arrow je .leftarrow .bailout: xor eax, eax epilog .uparrow: cmp [y], 0 je .bailout sub [y], 1 jmp .redraw .downarrow: cmp [y], r9d jae .bailout add [y], 1 jmp .redraw .rightarrow: cmp [x], r8d jae .bailout add [x], 1 jmp .redraw .shiftend: mov [x], r8d sub [x], 1 jmp .redraw .leftarrow: cmp [x], 0 je .bailout sub [x], 1 .redraw: call our_draw mov eax, 1 epilog ; a modified copy of tui_background$vtable so we can catch input and customise ; the draw method: dalign our_vtable: dq tui_object$cleanup, tui_background$clone, our_draw, tui_object$redraw, tui_object$updatedisplaylist, tui_object$sizechanged dq tui_object$timer, tui_object$layoutchanged, tui_object$move, tui_object$setfocus, tui_object$gotfocus, tui_object$lostfocus dq our_keyevent, tui_object$domodal, tui_object$endmodal, tui_object$exit, tui_object$calcbounds, tui_object$calcchildbounds dq tui_object$appendchild, tui_object$appendbastard, tui_object$prependchild, tui_object$contains, tui_object$getchildindex dq tui_object$removechild, tui_object$removebastard, tui_object$removeallchildren, tui_object$removeallbastards dq tui_object$getobjectsunderpoint, tui_object$flatten, tui_object$firekeyevent, tui_object$ontab, tui_object$onshifttab dq tui_object$setcursor, tui_object$showcursor, tui_object$hidecursor, tui_object$click, tui_object$clicked falign our_timer: prolog our_timer xor edi, edi mov esi, 3 call rng$int mov rdi, [bg] xor esi, esi mov edx, [.keys+rax*4] call our_keyevent ; keep the timer going: xor eax, eax epilog dalign .keys: dd 0x41, 0x42, 0x43, 0x44 ; a modified copy of epoll$default_vtable so we can catch timer events dalign timer_vtable: dq epoll$destroy, epoll$clone, io$connected, epoll$send, epoll$receive, io$error, our_timer public _start calign _start: ; initialise HeavyThing... call ht$init ; allocate enough room for our tui_background mov edi, tui_background_size call heap$alloc mov rbx, rax ; save it mov [bg], rax ; and in a global mov rdx, our_vtable ; use our custom vtable mov [rax], rdx ; save vtable mov rdi, rax ; setup for call to init_dd movq xmm0, [_math_onehundred] ; 100% width movq xmm1, [_math_onehundred] ; 100% height mov esi, '.' ; fillchar ansi_colors edx, 'lightgray', 'blue' ; colours call tui_background$init_dd ; create a "dummy" epoll object for our timer mov rdi, timer_vtable xor esi, esi call epoll$new mov edi, 100 ; 100ms timer mov rsi, rax ; epoll object it needs call epoll$timer_new mov rdi, rbx call tui_terminal$new call epoll$run ; doesn't come back include '../../ht_data.inc' Cheers |
|||
09 Jul 2017, 21:57 |
|
YONG 10 Jul 2017, 04:05
Tomasz Grysztar wrote:
Besides, why set the limit at 16 MB? Shouldn't the compiler be able to use as much memory as it needs? The compiler should only be bounded by the available physical memory. |
|||
10 Jul 2017, 04:05 |
|
YONG 10 Jul 2017, 04:13
redsock wrote: The only "master function list" is maintained via javascript on the upper-right corner of my site's search feature (it is scraped when the static pages for the site are constructed). One quick question: Where can I set the values for # of columns (80) and # of rows (25)? |
|||
10 Jul 2017, 04:13 |
|
YONG 10 Jul 2017, 06:36
redsock wrote: Morning coffee today resulted in a quick modification of the demo (noting I still didn't mess with bounds checking haha), this one randomly moves the X every 100ms |
|||
10 Jul 2017, 06:36 |
|
redsock 10 Jul 2017, 07:20
YONG wrote: One quick question: Where can I set the values for # of columns (80) and # of rows (25)? If OTOH you choose init_ii as the call, then the width and height are not percentage based (but the parameter order/registers changes obviously). The comments above the init_ii function will tell you which registers to fill with the integer width and height and you can omit the references to xmm regs from my demo. |
|||
10 Jul 2017, 07:20 |
|
YONG 10 Jul 2017, 10:15
redsock wrote: [If OTOH you choose init_ii as the call, ... |
|||
10 Jul 2017, 10:15 |
|
redsock 10 Jul 2017, 21:26
At least with all of the terminals I have tried over the years, resizing is always allowed unless you are on the console itself in runlevel 3 (which probably isn't what you want )
The black margins on the right and bottom are correct if your terminal size is >80x25. There are a number of ways to deal with that... if it were me, I would be inclined to center your 80x25 onscreen. The HT library makes use of a "panel-based" layout, whereby you can mix up percentage-based dynamic components and fixed size ones. Using the simple_vtable and tui_object itself you can create "spacer/container" objects to fill space as needed. The tui_simpleauth component I did does a similar thing to center its "enter your user/pass" space, if you look at tui_simpleauth$new and tui_simpleauth$nvsetup you can see how I constructed the layouts there. |
|||
10 Jul 2017, 21:26 |
|
YONG 11 Jul 2017, 03:13
redsock wrote: There are a number of ways to deal with that... if it were me, I would be inclined to center your 80x25 onscreen. The HT library makes use of a "panel-based" layout, whereby you can mix up percentage-based dynamic components and fixed size ones. Using the simple_vtable and tui_object itself you can create "spacer/container" objects to fill space as needed. Thanks! |
|||
11 Jul 2017, 03:13 |
|
YONG 15 Jul 2017, 09:52
@redsock:
Just a couple of quick questions: I tried to use the search at the upper right corner of your website. But nothing happened for a number of inputs: "prolog", "ansi_colors", and even "ht$init". Does the search support only a "selected" list of functions and/or routines? I tried to change the background color and the default character. It worked. But the upper left corner of the terminal always showed the initial blue box, even after moving the "X" away from it. Where can I set the default color for the initial blue box? Thanks in advance! |
|||
15 Jul 2017, 09:52 |
|
redsock 15 Jul 2017, 23:52
I modified the original example again
I fixed the size to 80x25, centered on a black background 100%x100% terminal. Fixed the bounds checking, and it now correctly hides the cursor. Does this version fixup what you were after? Code: include '../../ht_defaults.inc' include '../../ht.inc' globals { x dd 0 y dd 0 } falign our_draw: prolog our_draw push rdi ; ensure the cursor is hidden: mov rsi, [rdi] call qword [rsi+tui_vhidecursor] ; call tui_background's non-virtual fill: mov rdi, [rsp] call tui_background$nvfill pop rdi cmp dword [rdi+tui_width_ofs], 0 je .nothingtodo cmp dword [rdi+tui_height_ofs], 0 je .nothingtodo mov eax, [rdi+tui_width_ofs] mov r8, [rdi+tui_text_ofs] mov r9, [rdi+tui_attr_ofs] mov ecx, [y] mul ecx add eax, [x] shl eax, 2 ansi_colors r10d, 'red', 'darkblue' mov dword [r8+rax], 'X' mov dword [r9+rax], r10d .nothingtodo: mov rsi, [rdi] ; load the vtable call qword [rsi+tui_vupdatedisplaylist] epilog ; three arguments: rdi == our tui_background, esi == key, edx == esc_key ; NOTE: return zero in eax if firekeyevent should keep walking up "bubbling" ; and return nonzero in eax if firekeyevent should STOP falign our_keyevent: prolog our_keyevent ; check for cursor keys mov r8d, [rdi+tui_width_ofs] mov r9d, [rdi+tui_height_ofs] sub r8d, 1 sub r9d, 1 cmp edx, 0x41 ; up arrow je .uparrow cmp edx, 0x42 ; down arrow je .downarrow cmp edx, 0x43 ; right arrow je .rightarrow cmp edx, 0x46 ; end, well, shift-end je .shiftend cmp edx, 0x44 ; left arrow je .leftarrow .bailout: xor eax, eax epilog .uparrow: cmp [y], 0 je .bailout sub [y], 1 jmp .redraw .downarrow: cmp [y], r9d je .bailout add [y], 1 jmp .redraw .rightarrow: cmp [x], r8d je .bailout add [x], 1 jmp .redraw .shiftend: mov [x], r8d sub [x], 1 jmp .redraw .leftarrow: cmp [x], 0 je .bailout sub [x], 1 .redraw: call our_draw mov eax, 1 epilog ; a modified copy of tui_background$vtable so we can catch input and customise ; the draw method: dalign our_vtable: dq tui_object$cleanup, tui_background$clone, our_draw, tui_object$redraw, tui_object$updatedisplaylist, tui_object$sizechanged dq tui_object$timer, tui_object$layoutchanged, tui_object$move, tui_object$setfocus, tui_object$gotfocus, tui_object$lostfocus dq our_keyevent, tui_object$domodal, tui_object$endmodal, tui_object$exit, tui_object$calcbounds, tui_object$calcchildbounds dq tui_object$appendchild, tui_object$appendbastard, tui_object$prependchild, tui_object$contains, tui_object$getchildindex dq tui_object$removechild, tui_object$removebastard, tui_object$removeallchildren, tui_object$removeallbastards dq tui_object$getobjectsunderpoint, tui_object$flatten, tui_object$firekeyevent, tui_object$ontab, tui_object$onshifttab dq tui_object$setcursor, tui_object$showcursor, tui_object$hidecursor, tui_object$click, tui_object$clicked public _start calign _start: ; initialise HeavyThing... call ht$init ; allocate one 100%x100% background to hold everything mov edi, tui_background_size call heap$alloc movq xmm0, [_math_onehundred] movq xmm1, [_math_onehundred] mov rdi, rax mov esi, ' ' ansi_colors edx, 'lightgray', 'black' mov r12, rax call tui_background$init_dd ; make sure it aligns its children centered horizontally: mov dword [r12+tui_horizalign_ofs], tui_align_center ; use the default vtable mov qword [r12], tui_background$vtable ; default layout is vertical, so add a 50% high empty object mov edi, tui_object_size call heap$alloc push rax mov rdi, rax movq xmm0, [_math_onehundred] movq xmm1, [.half] call tui_object$init_dd pop rsi mov qword [rsi], tui_object$simple_vtable mov rdi, r12 mov rdx, [r12] call qword [rdx+tui_vappendchild] ; add our horizontally-centered 80x25 fixed size object next ; allocate enough room for our tui_background mov edi, tui_background_size call heap$alloc mov rbx, rax ; save it mov rdi, rax ; setup for call to init_dd mov esi, 80 ; width mov edx, 25 ; height mov ecx, ' ' ; fillchar ansi_colors r8d, 'lightgray', 'darkblue' ; colours call tui_background$init_ii mov qword [rbx], our_vtable ; use our custom vtable mov rdi, r12 mov rsi, rbx mov rdx, [r12] call qword [rdx+tui_vappendchild] ; and finally another 50% high padding below mov edi, tui_object_size call heap$alloc push rax mov rdi, rax movq xmm0, [_math_onehundred] movq xmm1, [.half] call tui_object$init_dd pop rsi mov qword [rsi], tui_object$simple_vtable mov rdi, r12 mov rdx, [r12] call qword [rdx+tui_vappendchild] mov rdi, r12 call tui_terminal$new call epoll$run ; doesn't come back dalign .half dq 50.0f include '../../ht_data.inc' |
|||
15 Jul 2017, 23:52 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.