Owner of https://lemmy.einval.net/
Mastodon: https://mastodon.social/@einval
RIF. Ugh, what a shame.
Hell yeah. No problem!
I can’t think of any one truly terrible episode I secretly enjoyed. I hate all of the episodes that were laser focused on Wesley Crusher, boy genius. If I had to pick a best of the worst from that pool I’d go with “The Game”. 😀
I haven’t had that happen to me yet, but it sounds annoying as hell. The “undetermined” language shouldn’t exist. That needs be a silent default. The user should be able select their primary language with a drop-down menu. The combo box would still exist but it’d be completely optional.
In your case it’d be nice if the “Select Language” drop-down was automatically set to the community’s default language. And maybe put a little red icon next to it when your language settings are incompatible.
What I use on Linux:
NASM uses Intel assembly syntax. If you want to learn and use AT&T syntax you can use GNU Assembler (as
) provided by the bintutils
package instead.
How I use it:
mkdir hello_world
cd hello_world
touch Makefile hello_world.asm
Note the indents below are supposed to be TAB characters, not spaces.
Makefile
all: hello_world
hello_world.o: hello_world.asm
nasm -o $@ -f elf32 -g $<
hello_world: hello_world.o
ld -m elf_i386 -g -o $@ $<
.PHONY: clean
clean:
rm -f hello_world *.o
hello_world.asm
; Assemble as a 32-bit program
bits 32
; Constants
SYS_EXIT equ 1 ; Kernel system call: exit()
SYS_WRITE equ 4 ; Kernel system call: write()
FD_STDOUT equ 1 ; System file descriptor to write to
EXIT_SUCCESS equ 0
; Variable storage
section .data
msg: db "hello world from ", 0
msg_len: equ $-msg
linefeed: db 0xa ; '\n'
linefeed_len: equ $-linefeed
; Program storage
section .text
global _start
_start:
; Set up stack frame
push ebp
mov ebp, esp
; Set base pointer to argv[0]
add ebp, 8
; Write "hello world from " message to stdout
mov eax, SYS_WRITE
mov ebx, FD_STDOUT
mov ecx, msg
mov edx, msg_len
int 80h
; Get length of argv[0]
push dword [ebp]
call strlen
mov edx, eax
; Write the program execution path to stdout
mov eax, SYS_WRITE
mov ebx, FD_STDOUT
mov ecx, [ebp]
; edx length already set
int 80h
; Write new line character
mov eax, SYS_WRITE
mov ebx, FD_STDOUT
mov ecx, linefeed
mov edx, linefeed_len
int 80h
; End of stack frame
pop ebp
; End program
mov eax, SYS_EXIT
mov ebx, EXIT_SUCCESS
int 80h
strlen:
; Set up stack frame
push ebp
mov ebp, esp
; Set base pointer to the first argument on the stack
; strlen(buffer);
; ^
add ebp, 8
; Save registers we plan to write to
push ecx
push esi
; Clear string direction flag
; (i.e. lodsb will *increment* esi)
cld
; Zero counter
xor ecx, ecx
; Load address of buffer into the "source index" register
mov esi, [ebp]
.loop:
; Read byte from esi
; Store byte in eax
lodsb
; Loop until string NUL terminator
cmp eax, 0
je .return
; else: Increment counter and continue
inc ecx
jmp .loop
.return:
; Return string length in eax
mov eax, ecx
; Restore written registers
pop esi
pop ecx
; End stack frame
pop ebp
; Pop stack argument
; 32-bit word is 4 bytes. We had one argument.
ret 4 * 1
$ make
nasm -o hello_world.o -f elf32 -g hello_world.asm
ld -m elf_i386 -g -o hello_world hello_world.o
$ ./hello_world
hello world from ./hello_world
Want to fire up your debugger immediately and break on the main entrypoint? No problem.
Makefile
gdb: hello_world
gdb -tui -ex 'b _start' -ex 'run' --args $<
Now you can clean the project, rebuild, and start a debugging session with one command…
$ make clean gdb
rm -f hello_world *.o
nasm -o hello_world.o -f elf32 -g hello_world.asm
ld -m elf_i386 -g -o hello_world hello_world.o
gdb -tui -ex 'b _start' -ex 'run' --args hello_world
# You're debugging the program in GDB now. Poof.
“Make it go, helmsman.” 👉
Oh cool! I’ll have to check it out. I love how people have been going back and reverse engineering old game engines lately.
Occasionally I’ll get hit with a few unwieldy conflicts. Usually it’s one or two lines, and always a whitespace issue because someone’s code style just has to be different.
Aliens: Special Edition